Fossil

Check-in Differences
Login

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

Difference From:

[f7914bfd] Version 2.3 - the 10th anniversary release (user: drh tags: trunk, release, version-2.3, date: 2017-07-21 03:19:30)

To:

[f014e156] Improvements to automatic hyperlink enabling and robot exclusion. (user: drh tags: trunk, date: 2017-10-16 13:54:46)

Changes to Makefile.in.

    47     47   USE_SEE = @USE_SEE@
    48     48   FOSSIL_ENABLE_MINIZ = @FOSSIL_ENABLE_MINIZ@
    49     49   
    50     50   include $(SRCDIR)/main.mk
    51     51   
    52     52   distclean: clean
    53     53   	rm -f autoconfig.h config.log Makefile
           54  +
           55  +reconfig:
           56  +	@AUTOREMAKE@
           57  +
           58  +# Automatically reconfigure whenever an autosetup file or one of the
           59  +# make source files change.
           60  +#
           61  +# The "touch" is necessary to avoid a make loop due to a new upstream
           62  +# feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
           63  +# if doing so will write different contents; otherwise, it leaves them
           64  +# alone so the mtime doesn't change.  This means that if you change one
           65  +# our depdendencies besides Makefile.in, we'll reconfigure but Makefile
           66  +# won't change, so this rule will remain out of date, so we'll reconfig
           67  +# but Makefile won't change, so we'll reconfig but... endlessly.
           68  +#
           69  +# This is also why we repeat the reconfig target's command here instead
           70  +# of delegating to it with "$(MAKE) reconfig": having children running
           71  +# around interfering makes this failure mode even worse.
           72  +Makefile: @srcdir@/Makefile.in $(SRCDIR)/main.mk @AUTODEPS@
           73  +	@AUTOREMAKE@
           74  +	touch @builddir@/Makefile

Changes to VERSION.

     1         -2.3
            1  +2.4

Changes to auto.def.

   188    188       define-append EXTRA_LDFLAGS -static
   189    189       msg-result "Trying to link statically"
   190    190   } else {
   191    191       define-append EXTRA_CFLAGS -DFOSSIL_DYNAMIC_BUILD=1
   192    192       define FOSSIL_DYNAMIC_BUILD
   193    193   }
   194    194   
          195  +# Check for libraries that need to be sorted out early
          196  +cc-check-function-in-lib iconv iconv
          197  +
   195    198   # Helper for OpenSSL checking
   196    199   proc check-for-openssl {msg {cflags {}} {libs {-lssl -lcrypto}}} {
   197    200       msg-checking "Checking for $msg..."
   198    201       set rc 0
   199    202       if {[is_mingw]} {
   200    203           lappend libs -lgdi32 -lwsock32 -lcrypt32
   201    204       }
................................................................................
   456    459   cc-check-function-in-lib gethostbyname nsl
   457    460   if {![cc-check-function-in-lib socket {socket network}]} {
   458    461       # Last resort, may be Windows
   459    462       if {[is_mingw]} {
   460    463           define-append LIBS -lwsock32
   461    464       }
   462    465   }
   463         -cc-check-function-in-lib iconv iconv
   464    466   cc-check-functions utime
   465    467   cc-check-functions usleep
   466    468   cc-check-functions strchrnul
   467    469   
   468    470   # Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
   469    471   if {![cc-check-functions getloadavg]} {
   470    472     define FOSSIL_OMIT_LOAD_AVERAGE 1

Changes to autosetup/system.tcl.

   203    203   					set cond [expr {!$cond}]
   204    204   				}
   205    205   			}
   206    206   			continue
   207    207   		}
   208    208   		lappend result $line
   209    209   	}
   210         -	writefile $out [string map $mapping [join $result \n]]\n
   211         -
   212         -	msg-result "Created [relative-path $out] from [relative-path $template]"
          210  +    write-if-changed $out [string map $mapping [join $result \n]]\n {
          211  +        msg-result "Created [relative-path $out] from [relative-path $template]"
          212  +    }
   213    213   }
   214    214   
   215    215   # build/host tuples and cross-compilation prefix
   216    216   set build [opt-val build]
   217    217   define build_alias $build
   218    218   if {$build eq ""} {
   219    219   	define build [config_guess]

Changes to src/add.c.

   274    274   **    --case-sensitive <BOOL> Override the case-sensitive setting.
   275    275   **    --dotfiles              include files beginning with a dot (".")
   276    276   **    -f|--force              Add files without prompting
   277    277   **    --ignore <CSG>          Ignore unmanaged files matching patterns from
   278    278   **                            the comma separated list of glob patterns.
   279    279   **    --clean <CSG>           Also ignore files matching patterns from
   280    280   **                            the comma separated list of glob patterns.
   281         -**    --no-dir-symlinks       Disables support for directory symlinks.
   282    281   **
   283    282   ** See also: addremove, rm
   284    283   */
   285    284   void add_cmd(void){
   286    285     int i;                     /* Loop counter */
   287    286     int vid;                   /* Currently checked out version */
   288    287     int nRoot;                 /* Full path characters in g.zLocalRoot */
................................................................................
   440    439   **
   441    440   ** Options:
   442    441   **   --soft                  Skip removing files from the checkout.
   443    442   **                           This supersedes the --hard option.
   444    443   **   --hard                  Remove files from the checkout.
   445    444   **   --case-sensitive <BOOL> Override the case-sensitive setting.
   446    445   **   -n|--dry-run            If given, display instead of run actions.
   447         -**   --no-dir-symlinks       Disables support for directory symlinks.
   448    446   **
   449    447   ** See also: addremove, add
   450    448   */
   451    449   void delete_cmd(void){
   452    450     int i;
   453    451     int removeFiles;
   454    452     int dryRunFlag;
................................................................................
   622    620   **   --case-sensitive <BOOL> Override the case-sensitive setting.
   623    621   **   --dotfiles              Include files beginning with a dot (".")
   624    622   **   --ignore <CSG>          Ignore unmanaged files matching patterns from
   625    623   **                           the comma separated list of glob patterns.
   626    624   **   --clean <CSG>           Also ignore files matching patterns from
   627    625   **                           the comma separated list of glob patterns.
   628    626   **   -n|--dry-run            If given, display instead of run actions.
   629         -**   --no-dir-symlinks       Disables support for directory symlinks.
   630    627   **
   631    628   ** See also: add, rm
   632    629   */
   633    630   void addremove_cmd(void){
   634    631     Blob path;
   635    632     const char *zCleanFlag = find_option("clean",0,1);
   636    633     const char *zIgnoreFlag = find_option("ignore",0,1);
................................................................................
   850    847   **
   851    848   ** Options:
   852    849   **   --soft                  Skip moving files within the checkout.
   853    850   **                           This supersedes the --hard option.
   854    851   **   --hard                  Move files within the checkout.
   855    852   **   --case-sensitive <BOOL> Override the case-sensitive setting.
   856    853   **   -n|--dry-run            If given, display instead of run actions.
   857         -**   --no-dir-symlinks       Disables support for directory symlinks.
   858    854   **
   859    855   ** See also: changes, status
   860    856   */
   861    857   void mv_cmd(void){
   862    858     int i;
   863    859     int vid;
   864    860     int moveFiles;

Changes to src/blob.c.

  1167   1167       }else{
  1168   1168         z[--j] = z[i];
  1169   1169       }
  1170   1170     }
  1171   1171   }
  1172   1172   
  1173   1173   /*
  1174         -** Shell-escape the given string.  Append the result to a blob.
         1174  +** pBlob is a shell command under construction.  This routine safely
         1175  +** appends argument zIn.
         1176  +**
         1177  +** The argument is escaped if it contains white space or other characters
         1178  +** that need to be escaped for the shell.  If zIn contains characters
         1179  +** that cannot be safely escaped, then throw a fatal error.
         1180  +**
         1181  +** The argument is expected to a filename of some kinds.  As shell commands
         1182  +** commonly have command-line options that begin with "-" and since we
         1183  +** do not want an attacker to be able to invoke these switches using
         1184  +** filenames that begin with "-", if zIn begins with "-", prepend
         1185  +** an additional "./".
  1175   1186   */
  1176         -void shell_escape(Blob *pBlob, const char *zIn){
         1187  +void blob_append_escaped_arg(Blob *pBlob, const char *zIn){
         1188  +  int i;
         1189  +  char c;
         1190  +  int needEscape = 0;
  1177   1191     int n = blob_size(pBlob);
  1178         -  int k = strlen(zIn);
  1179         -  int i, c;
  1180         -  char *z;
         1192  +  char *z = blob_buffer(pBlob);
         1193  +#if defined(_WIN32)
         1194  +  const char cQuote = '"';    /* Use "..." quoting on windows */
         1195  +#else
         1196  +  const char cQuote = '\'';   /* Use '...' quoting on unix */
         1197  +#endif
         1198  +
  1181   1199     for(i=0; (c = zIn[i])!=0; i++){
  1182         -    if( fossil_isspace(c) || c=='"' || (c=='\\' && zIn[i+1]!=0) ){
  1183         -      blob_appendf(pBlob, "\"%s\"", zIn);
  1184         -      z = blob_buffer(pBlob);
  1185         -      for(i=n+1; i<=n+k; i++){
  1186         -        if( z[i]=='"' ) z[i] = '_';
  1187         -      }
  1188         -      return;
         1200  +    if( c==cQuote || c=='\\' || c<' ' || c==';' || c=='*' || c=='?' || c=='[') {
         1201  +      Blob bad;
         1202  +      blob_token(pBlob, &bad);
         1203  +      fossil_fatal("the [%s] argument to the \"%s\" command contains "
         1204  +                   "a character (ascii 0x%02x) that is a security risk",
         1205  +                   zIn, blob_str(&bad), c);
         1206  +    }
         1207  +    if( !needEscape && !fossil_isalnum(c) && c!='/' && c!='.' && c!='_' ){
         1208  +      needEscape = 1;
  1189   1209       }
  1190   1210     }
         1211  +  if( n>0 && !fossil_isspace(z[n-1]) ){
         1212  +    blob_append(pBlob, " ", 1);
         1213  +  }
         1214  +  if( needEscape ) blob_append(pBlob, &cQuote, 1);
         1215  +  if( zIn[0]=='-' ) blob_append(pBlob, "./", 2);
  1191   1216     blob_append(pBlob, zIn, -1);
         1217  +  if( needEscape ) blob_append(pBlob, &cQuote, 1);
  1192   1218   }
  1193   1219   
  1194   1220   /*
  1195   1221   ** A read(2)-like impl for the Blob class. Reads (copies) up to nLen
  1196   1222   ** bytes from pIn, starting at position pIn->iCursor, and copies them
  1197   1223   ** to pDest (which must be valid memory at least nLen bytes long).
  1198   1224   **

Changes to src/branch.c.

   155    155       fossil_fatal("trouble committing manifest: %s", g.zErrMsg);
   156    156     }
   157    157     db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
   158    158     if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
   159    159       fossil_fatal("%s", g.zErrMsg);
   160    160     }
   161    161     assert( blob_is_reset(&branch) );
   162         -  content_deltify(rootid, brid, 0);
          162  +  content_deltify(rootid, &brid, 1, 0);
   163    163     zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
   164    164     fossil_print("New branch: %s\n", zUuid);
   165    165     if( g.argc==3 ){
   166    166       fossil_print(
   167    167         "\n"
   168    168         "Note: the local check-out has not been updated to the new\n"
   169    169         "      branch.  To begin working on the new branch, do this:\n"
................................................................................
   386    386     Stmt q;
   387    387     double rNow;
   388    388     int show_colors = PB("colors");
   389    389     login_check_credentials();
   390    390     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
   391    391     style_header("Branches");
   392    392     style_adunit_config(ADUNIT_RIGHT_OK);
   393         -  style_submenu_checkbox("colors", "Use Branch Colors", 0);
          393  +  style_submenu_checkbox("colors", "Use Branch Colors", 0, 0);
   394    394     login_anonymous_available();
   395    395   
   396    396     db_prepare(&q, brlistQuery/*works-like:""*/);
   397    397     rNow = db_double(0.0, "SELECT julianday('now')");
   398    398     @ <div class="brlist"><table id="branchlisttable">
   399    399     @ <thead><tr>
   400    400     @ <th>Branch Name</th>

Changes to src/browse.c.

   751    751         if( p->pChild!=0 && p->nFullName>nD ) nFile++;
   752    752       }
   753    753       zObjType = "Folders";
   754    754     }else{
   755    755       zObjType = "Files";
   756    756     }
   757    757   
   758         -  style_submenu_checkbox("nofiles", "Folders Only", 0);
          758  +  style_submenu_checkbox("nofiles", "Folders Only", 0, 0);
   759    759   
   760    760     if( zCI ){
   761    761       @ <h2>%s(zObjType) from
   762    762       if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
   763    763         @ "%h(zCI)"
   764    764       }
   765    765       @ [%z(href("vinfo?name=%!S",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))

Changes to src/checkin.c.

   415    415   **    --rel-paths       Display pathnames relative to the current working
   416    416   **                      directory.
   417    417   **    --hash            Verify file status using hashing rather than
   418    418   **                      relying on file mtimes.
   419    419   **    --case-sensitive <BOOL>  Override case-sensitive setting.
   420    420   **    --dotfiles        Include unmanaged files beginning with a dot.
   421    421   **    --ignore <CSG>    Ignore unmanaged files matching CSG glob patterns.
   422         -**    --no-dir-symlinks Disables support for directory symlinks.
   423    422   **
   424    423   ** Options specific to the changes command:
   425    424   **    --header          Identify the repository if report is non-empty.
   426    425   **    -v|--verbose      Say "(none)" if the change report is empty.
   427    426   **    --classify        Start each line with the file's change type.
   428    427   **    --no-classify     Do not print file change types.
   429    428   **
................................................................................
   824    823   **
   825    824   ** Options:
   826    825   **    --abs-paths      Display absolute pathnames.
   827    826   **    --case-sensitive <BOOL> override case-sensitive setting
   828    827   **    --dotfiles       include files beginning with a dot (".")
   829    828   **    --header         Identify the repository if there are extras
   830    829   **    --ignore <CSG>   ignore files matching patterns from the argument
   831         -**    --no-dir-symlinks Disables support for directory symlinks.
   832    830   **    --rel-paths      Display pathnames relative to the current working
   833    831   **                     directory.
   834    832   **
   835    833   ** See also: changes, clean, status
   836    834   */
   837    835   void extras_cmd(void){
   838    836     Blob report = BLOB_INITIALIZER;
................................................................................
   854    852     /* We should be done with options.. */
   855    853     verify_all_options();
   856    854   
   857    855     if( zIgnoreFlag==0 ){
   858    856       zIgnoreFlag = db_get("ignore-glob", 0);
   859    857     }
   860    858     pIgnore = glob_create(zIgnoreFlag);
          859  +  /* Always consider symlinks. */
          860  +  g.allowSymlinks = db_allow_symlinks_by_default();
   861    861     locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
   862    862     glob_free(pIgnore);
   863    863   
   864    864     blob_zero(&report);
   865    865     status_report(&report, flags);
   866    866     if( blob_size(&report) ){
   867    867       if( showHdr ){
................................................................................
   899    899   ** ever be deleted.  Files and subdirectories whose names begin with "."
   900    900   ** are automatically ignored unless the --dotfiles option is used.
   901    901   **
   902    902   ** The default values for --clean, --ignore, and --keep are determined by
   903    903   ** the (versionable) clean-glob, ignore-glob, and keep-glob settings.
   904    904   **
   905    905   ** The --verily option ignores the keep-glob and ignore-glob settings and
   906         -** turns on the options --force, --emptydirs, --dotfiles, --disable-undo,
   907         -** and --no-dir-symlinks.  Use the --verily option when you really want
   908         -** to clean up everything.  Extreme care should be exercised when using
   909         -** the --verily option.
          906  +** turns on --force, --emptydirs, --dotfiles, and --disable-undo.  Use the
          907  +** --verily option when you really want to clean up everything.  Extreme
          908  +** care should be exercised when using the --verily option.
   910    909   **
   911    910   ** Options:
   912    911   **    --allckouts      Check for empty directories within any checkouts
   913    912   **                     that may be nested within the current one.  This
   914    913   **                     option should be used with great care because the
   915    914   **                     empty-dirs setting (and other applicable settings)
   916    915   **                     belonging to the other repositories, if any, will
................................................................................
   932    931   **                     that were removed will be removed as well.
   933    932   **    -f|--force       Remove files without prompting.
   934    933   **    -i|--prompt      Prompt before removing each file.  This option
   935    934   **                     implies the --disable-undo option.
   936    935   **    -x|--verily      WARNING: Removes everything that is not a managed
   937    936   **                     file or the repository itself.  This option
   938    937   **                     implies the --force, --emptydirs, --dotfiles, and
   939         -**                     --disable-undo, and --no-dir-symlinks options.
          938  +**                     --disable-undo options.
   940    939   **                     Furthermore, it completely disregards the keep-glob
   941    940   **                     and ignore-glob settings.  However, it does honor
   942    941   **                     the --ignore and --keep options.
   943    942   **    --clean <CSG>    WARNING: Never prompt to delete any files matching
   944    943   **                     this comma separated list of glob patterns.  Also,
   945    944   **                     deletions of any files matching this pattern list
   946    945   **                     cannot be undone.
................................................................................
   948    947   **                     comma separated list of glob patterns.
   949    948   **    --keep <CSG>     Keep files matching this comma separated
   950    949   **                     list of glob patterns.
   951    950   **    -n|--dry-run     Delete nothing, but display what would have been
   952    951   **                     deleted.
   953    952   **    --no-prompt      This option disables prompting the user for input
   954    953   **                     and assumes an answer of 'No' for every question.
   955         -**    --no-dir-symlinks Disables support for directory symlinks.
   956    954   **    --temp           Remove only Fossil-generated temporary files.
   957    955   **    -v|--verbose     Show all files as they are removed.
   958    956   **
   959    957   ** See also: addremove, extras, status
   960    958   */
   961    959   void clean_cmd(void){
   962    960     int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
................................................................................
   997    995     db_must_be_within_tree();
   998    996     if( find_option("verily","x",0)!=0 ){
   999    997       verilyFlag = allFileFlag = allDirFlag = 1;
  1000    998       emptyDirsFlag = 1;
  1001    999       disableUndo = 1;
  1002   1000       scanFlags |= SCAN_ALL;
  1003   1001       zCleanFlag = 0;
  1004         -    g.fNoDirSymlinks = 1; /* Forbid symlink directory traversal. */
  1005         -    g.allowSymlinks = 1;  /* Treat symlink files as content. */
  1006   1002     }
  1007   1003     if( zIgnoreFlag==0 && !verilyFlag ){
  1008   1004       zIgnoreFlag = db_get("ignore-glob", 0);
  1009   1005     }
  1010   1006     if( zKeepFlag==0 && !verilyFlag ){
  1011   1007       zKeepFlag = db_get("keep-glob", 0);
  1012   1008     }
................................................................................
  1015   1011     }
  1016   1012     if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
  1017   1013     verify_all_options();
  1018   1014     pIgnore = glob_create(zIgnoreFlag);
  1019   1015     pKeep = glob_create(zKeepFlag);
  1020   1016     pClean = glob_create(zCleanFlag);
  1021   1017     nRoot = (int)strlen(g.zLocalRoot);
         1018  +  /* Always consider symlinks. */
         1019  +  g.allowSymlinks = db_allow_symlinks_by_default();
  1022   1020     if( !dirsOnlyFlag ){
  1023   1021       Stmt q;
  1024   1022       Blob repo;
  1025   1023       if( !dryRunFlag && !disableUndo ) undo_begin();
  1026   1024       locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
  1027   1025       db_prepare(&q,
  1028   1026           "SELECT %Q || pathname FROM sfile"
................................................................................
  2398   2396         fossil_print("possible unresolved merge conflict in %s\n",
  2399   2397                      blob_str(&fname));
  2400   2398         blob_reset(&fname);
  2401   2399       }
  2402   2400       nrid = content_put(&content);
  2403   2401       blob_reset(&content);
  2404   2402       if( rid>0 ){
  2405         -      content_deltify(rid, nrid, 0);
         2403  +      content_deltify(rid, &nrid, 1, 0);
  2406   2404       }
  2407   2405       db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
  2408   2406       db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
  2409   2407     }
  2410   2408     db_finalize(&q);
  2411   2409     if( nConflict && !allowConflict ){
  2412   2410       fossil_fatal("abort due to unresolved merge conflicts; "
................................................................................
  2505   2503     }
  2506   2504     db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nvid);
  2507   2505     if( manifest_crosslink(nvid, &manifest,
  2508   2506                            dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
  2509   2507       fossil_fatal("%s", g.zErrMsg);
  2510   2508     }
  2511   2509     assert( blob_is_reset(&manifest) );
  2512         -  content_deltify(vid, nvid, 0);
         2510  +  content_deltify(vid, &nvid, 1, 0);
  2513   2511     zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
  2514   2512   
  2515   2513     db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
  2516   2514                    " WHERE id=-4");
  2517   2515     while( db_step(&q)==SQLITE_ROW ){
  2518   2516       const char *zIntegrateUuid = db_column_text(&q, 0);
  2519   2517       if( is_a_leaf(db_column_int(&q, 1)) ){

Changes to src/configure.c.

    33     33   #define CONFIGSET_SKIN      0x000002     /* WWW interface appearance */
    34     34   #define CONFIGSET_TKT       0x000004     /* Ticket configuration */
    35     35   #define CONFIGSET_PROJ      0x000008     /* Project name */
    36     36   #define CONFIGSET_SHUN      0x000010     /* Shun settings */
    37     37   #define CONFIGSET_USER      0x000020     /* The USER table */
    38     38   #define CONFIGSET_ADDR      0x000040     /* The CONCEALED table */
    39     39   #define CONFIGSET_XFER      0x000080     /* Transfer configuration */
           40  +#define CONFIGSET_ALIAS     0x000100     /* URL Aliases */
    40     41   
    41         -#define CONFIGSET_ALL       0x0000ff     /* Everything */
           42  +#define CONFIGSET_ALL       0x0001ff     /* Everything */
    42     43   
    43     44   #define CONFIGSET_OVERWRITE 0x100000     /* Causes overwrite instead of merge */
    44         -#define CONFIGSET_OLDFORMAT 0x200000     /* Use the legacy format */
    45     45   
    46     46   /*
    47     47   ** This mask is used for the common TH1 configuration settings (i.e. those
    48     48   ** that are not specific to one particular subsystem, such as the transfer
    49     49   ** subsystem).
    50     50   */
    51     51   #define CONFIGSET_TH1       (CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER)
................................................................................
    65     65     { "/skin",         CONFIGSET_SKIN | CONFIGSET_CSS,
    66     66                                         "Web interface appearance settings"    },
    67     67     { "/css",          CONFIGSET_CSS,   "Style sheet"                          },
    68     68     { "/shun",         CONFIGSET_SHUN,  "List of shunned artifacts"            },
    69     69     { "/ticket",       CONFIGSET_TKT,   "Ticket setup",                        },
    70     70     { "/user",         CONFIGSET_USER,  "Users and privilege settings"         },
    71     71     { "/xfer",         CONFIGSET_XFER,  "Transfer setup",                      },
           72  +  { "/alias",        CONFIGSET_ALIAS, "URL Aliases",                         },
    72     73     { "/all",          CONFIGSET_ALL,   "All of the above"                     },
    73     74   };
    74     75   
    75     76   
    76     77   /*
    77     78   ** The following is a list of settings that we are willing to
    78     79   ** transfer.
................................................................................
   152    153   
   153    154     { "@user",                  CONFIGSET_USER },
   154    155   
   155    156     { "@concealed",             CONFIGSET_ADDR },
   156    157   
   157    158     { "@shun",                  CONFIGSET_SHUN },
   158    159   
          160  +  { "@alias",                 CONFIGSET_ALIAS },
          161  +
   159    162     { "xfer-common-script",     CONFIGSET_XFER },
   160    163     { "xfer-push-script",       CONFIGSET_XFER },
   161    164     { "xfer-commit-script",     CONFIGSET_XFER },
   162    165     { "xfer-ticket-script",     CONFIGSET_XFER },
   163    166   
   164    167   };
   165    168   static int iConfig = 0;
................................................................................
   168    171   ** Return name of first configuration property matching the given mask.
   169    172   */
   170    173   const char *configure_first_name(int iMask){
   171    174     iConfig = 0;
   172    175     return configure_next_name(iMask);
   173    176   }
   174    177   const char *configure_next_name(int iMask){
   175         -  if( iMask & CONFIGSET_OLDFORMAT ){
   176         -    while( iConfig<count(aConfig) ){
   177         -      if( aConfig[iConfig].groupMask & iMask ){
   178         -        return aConfig[iConfig++].zName;
   179         -      }else{
   180         -        iConfig++;
   181         -      }
   182         -    }
   183         -  }else{
   184         -    if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
   185         -      iConfig = count(aGroupName);
   186         -      return "/all";
   187         -    }
   188         -    while( iConfig<count(aGroupName)-1 ){
   189         -      if( aGroupName[iConfig].groupMask & iMask ){
   190         -        return aGroupName[iConfig++].zName;
   191         -      }else{
   192         -        iConfig++;
   193         -      }
          178  +  if( iConfig==0 && (iMask & CONFIGSET_ALL)==CONFIGSET_ALL ){
          179  +    iConfig = count(aGroupName);
          180  +    return "/all";
          181  +  }
          182  +  while( iConfig<count(aGroupName)-1 ){
          183  +    if( aGroupName[iConfig].groupMask & iMask ){
          184  +      return aGroupName[iConfig++].zName;
          185  +    }else{
          186  +      iConfig++;
   194    187       }
   195    188     }
   196    189     return 0;
   197    190   }
   198    191   
   199    192   /*
   200    193   ** Return a pointer to a string that contains the RHS of an IN operator
................................................................................
   242    235         }
   243    236         if( !g.perm.RdAddr ){
   244    237           m &= ~CONFIGSET_ADDR;
   245    238         }
   246    239         return m;
   247    240       }
   248    241     }
          242  +  if( strncmp(zName, "walias:/", 8)==0 ){
          243  +    return CONFIGSET_ALIAS;
          244  +  }
   249    245     return 0;
   250    246   }
   251    247   
   252    248   /*
   253         -** zName is one of the special configuration names that refers to an entire
   254         -** table rather than a single entry in CONFIG.  Special names are "@reportfmt"
   255         -** and "@shun" and "@user".  This routine writes SQL text into pOut that when
   256         -** evaluated will populate the corresponding table with data.
   257         -*/
   258         -void configure_render_special_name(const char *zName, Blob *pOut){
   259         -  Stmt q;
   260         -  if( fossil_strcmp(zName, "@shun")==0 ){
   261         -    db_prepare(&q, "SELECT uuid FROM shun");
   262         -    while( db_step(&q)==SQLITE_ROW ){
   263         -      blob_appendf(pOut, "INSERT OR IGNORE INTO shun VALUES('%s');\n",
   264         -        db_column_text(&q, 0)
   265         -      );
   266         -    }
   267         -    db_finalize(&q);
   268         -  }else if( fossil_strcmp(zName, "@reportfmt")==0 ){
   269         -    db_prepare(&q, "SELECT title, cols, sqlcode FROM reportfmt");
   270         -    while( db_step(&q)==SQLITE_ROW ){
   271         -      blob_appendf(pOut, "INSERT INTO _xfer_reportfmt(title,cols,sqlcode)"
   272         -                         " VALUES(%Q,%Q,%Q);\n",
   273         -        db_column_text(&q, 0),
   274         -        db_column_text(&q, 1),
   275         -        db_column_text(&q, 2)
   276         -      );
   277         -    }
   278         -    db_finalize(&q);
   279         -  }else if( fossil_strcmp(zName, "@user")==0 ){
   280         -    db_prepare(&q,
   281         -        "SELECT login, CASE WHEN length(pw)==40 THEN pw END,"
   282         -        "       cap, info, quote(photo) FROM user");
   283         -    while( db_step(&q)==SQLITE_ROW ){
   284         -      blob_appendf(pOut, "INSERT INTO _xfer_user(login,pw,cap,info,photo)"
   285         -                         " VALUES(%Q,%Q,%Q,%Q,%s);\n",
   286         -        db_column_text(&q, 0),
   287         -        db_column_text(&q, 1),
   288         -        db_column_text(&q, 2),
   289         -        db_column_text(&q, 3),
   290         -        db_column_text(&q, 4)
   291         -      );
   292         -    }
   293         -    db_finalize(&q);
   294         -  }else if( fossil_strcmp(zName, "@concealed")==0 ){
   295         -    db_prepare(&q, "SELECT hash, content FROM concealed");
   296         -    while( db_step(&q)==SQLITE_ROW ){
   297         -      blob_appendf(pOut, "INSERT OR IGNORE INTO concealed(hash,content)"
   298         -                         " VALUES(%Q,%Q);\n",
   299         -        db_column_text(&q, 0),
   300         -        db_column_text(&q, 1)
   301         -      );
   302         -    }
   303         -    db_finalize(&q);
   304         -  }
   305         -}
   306         -
   307         -/*
   308         -** Two SQL functions:
   309         -**
   310         -**        config_is_reset(int)
   311         -**        config_reset(int)
   312         -**
   313         -** The config_is_reset() function takes the integer valued argument and
   314         -** ANDs it against the static variable "configHasBeenReset" below.  The
   315         -** function returns TRUE or FALSE depending on the result depending on
   316         -** whether or not the corresponding configuration table has been reset.  The
   317         -** config_reset() function adds the bits to "configHasBeenReset" that
   318         -** are given in the argument.
   319         -**
   320         -** These functions are used below in the WHEN clause of a trigger to
   321         -** get the trigger to fire exactly once.
   322         -*/
   323         -static int configHasBeenReset = 0;
   324         -static void config_is_reset_function(
   325         -  sqlite3_context *context,
   326         -  int argc,
   327         -  sqlite3_value **argv
   328         -){
   329         -  int m = sqlite3_value_int(argv[0]);
   330         -  sqlite3_result_int(context, (configHasBeenReset&m)!=0 );
   331         -}
   332         -static void config_reset_function(
   333         -  sqlite3_context *context,
   334         -  int argc,
   335         -  sqlite3_value **argv
   336         -){
   337         -  int m = sqlite3_value_int(argv[0]);
   338         -  configHasBeenReset |= m;
   339         -}
   340         -
   341         -/*
   342         -** Create the temporary _xfer_reportfmt and _xfer_user tables that are
   343         -** necessary in order to evaluate the SQL text generated by the
   344         -** configure_render_special_name() routine.
   345         -**
   346         -** If replaceFlag is true, then the setup is such that the content in
   347         -** the SQL text will completely replace the current repository configuration.
   348         -** If replaceFlag is false, then the SQL text will be merged with the
   349         -** existing configuration.  When merging, existing values take priority
   350         -** over SQL text values.
   351         -*/
   352         -void configure_prepare_to_receive(int replaceFlag){
   353         -  static const char zSQL1[] =
   354         -    @ CREATE TEMP TABLE _xfer_reportfmt(
   355         -    @    rn integer primary key,  -- Report number
   356         -    @    owner text,              -- Owner of this report format (not used)
   357         -    @    title text UNIQUE ON CONFLICT IGNORE,  -- Title of this report
   358         -    @    cols text,               -- A color-key specification
   359         -    @    sqlcode text             -- An SQL SELECT statement for this report
   360         -    @ );
   361         -    @ CREATE TEMP TABLE _xfer_user(
   362         -    @   uid INTEGER PRIMARY KEY,        -- User ID
   363         -    @   login TEXT UNIQUE ON CONFLICT IGNORE,   -- login name of the user
   364         -    @   pw TEXT,                        -- password
   365         -    @   cap TEXT,                       -- Capabilities of this user
   366         -    @   cookie TEXT,                    -- WWW login cookie
   367         -    @   ipaddr TEXT,                    -- IP address for which cookie is valid
   368         -    @   cexpire DATETIME,               -- Time when cookie expires
   369         -    @   info TEXT,                      -- contact information
   370         -    @   photo BLOB                      -- JPEG image of this user
   371         -    @ );
   372         -    @ INSERT INTO _xfer_reportfmt
   373         -    @    SELECT rn,owner,title,cols,sqlcode FROM reportfmt;
   374         -    @ INSERT INTO _xfer_user
   375         -    @    SELECT uid,login,pw,cap,cookie,ipaddr,cexpire,info,photo FROM user;
   376         -  ;
   377         -  assert( strchr(zSQL1,'%')==0 );
   378         -  db_multi_exec(zSQL1 /*works-like:""*/);
   379         -
   380         -  /* When the replace flag is set, add triggers that run the first time
   381         -  ** that new data is seen.  The triggers run only once and delete all the
   382         -  ** existing data.
   383         -  */
   384         -  if( replaceFlag ){
   385         -    static const char zSQL2[] =
   386         -      @ CREATE TRIGGER _xfer_r1 BEFORE INSERT ON _xfer_reportfmt
   387         -      @ WHEN NOT config_is_reset(2) BEGIN
   388         -      @   DELETE FROM _xfer_reportfmt;
   389         -      @   SELECT config_reset(2);
   390         -      @ END;
   391         -      @ CREATE TRIGGER _xfer_r2 BEFORE INSERT ON _xfer_user
   392         -      @ WHEN NOT config_is_reset(16) BEGIN
   393         -      @   DELETE FROM _xfer_user;
   394         -      @   SELECT config_reset(16);
   395         -      @ END;
   396         -      @ CREATE TEMP TRIGGER _xfer_r3 BEFORE INSERT ON shun
   397         -      @ WHEN NOT config_is_reset(8) BEGIN
   398         -      @   DELETE FROM shun;
   399         -      @   SELECT config_reset(8);
   400         -      @ END;
   401         -    ;
   402         -    sqlite3_create_function(g.db, "config_is_reset", 1, SQLITE_UTF8, 0,
   403         -         config_is_reset_function, 0, 0);
   404         -    sqlite3_create_function(g.db, "config_reset", 1, SQLITE_UTF8, 0,
   405         -         config_reset_function, 0, 0);
   406         -    configHasBeenReset = 0;
   407         -    assert( strchr(zSQL2,'%')==0 );
   408         -    db_multi_exec(zSQL2 /*works-like:""*/);
   409         -  }
   410         -}
   411         -
   412         -/*
   413         -** After receiving configuration data, call this routine to transfer
   414         -** the results into the main database.
   415         -*/
   416         -void configure_finalize_receive(void){
   417         -  static const char zSQL[] =
   418         -    @ DELETE FROM user;
   419         -    @ INSERT INTO user SELECT * FROM _xfer_user;
   420         -    @ DELETE FROM reportfmt;
   421         -    @ INSERT INTO reportfmt SELECT * FROM _xfer_reportfmt;
   422         -    @ DROP TABLE _xfer_user;
   423         -    @ DROP TABLE _xfer_reportfmt;
   424         -  ;
   425         -  assert( strchr(zSQL,'%')==0 );
   426         -  db_multi_exec(zSQL /*works-like:""*/);
   427         -}
          249  +** A mask of all configuration tables that have been reset already.
          250  +*/
          251  +static int configHasBeenReset = 0;
   428    252   
   429    253   /*
   430    254   ** Mask of modified configuration sets
   431    255   */
   432    256   static int rebuildMask = 0;
   433    257   
   434    258   /*
................................................................................
   512    336   **    /concealed  $MTIME $HASH content $VALUE
   513    337   **
   514    338   ** OLD FORMAT:
   515    339   **
   516    340   ** The old format is retained for backwards compatibility, but is deprecated.
   517    341   ** The cutover from old format to new was on 2011-04-25.  After sufficient
   518    342   ** time has passed, support for the old format will be removed.
          343  +** Update: Support for the old format was remoed on 2017-09-20.
   519    344   **
   520    345   ** zName is either the NAME of an element of the CONFIG table, or else
   521    346   ** one of the special names "@shun", "@reportfmt", "@user", or "@concealed".
   522    347   ** If zName is a CONFIG table name, then CONTENT replaces (overwrites) the
   523    348   ** element in the CONFIG table.  For one of the @-labels, CONTENT is raw
   524    349   ** SQL that is evaluated.  Note that the raw SQL in CONTENT might not
   525    350   ** insert directly into the target table but might instead use a proxy
................................................................................
   607    432         blob_append_sql(&sql, " WHERE \"%w\"=%s AND mtime<%s",
   608    433                      aType[ii].zPrimKey, azToken[1]/*safe-for-%s*/,
   609    434                      azToken[0]/*safe-for-%s*/);
   610    435         db_multi_exec("%s", blob_sql_text(&sql));
   611    436       }
   612    437       blob_reset(&sql);
   613    438       rebuildMask |= thisMask;
   614         -  }else{
   615         -    /* Otherwise, the old format */
   616         -    if( (configure_is_exportable(zName) & groupMask)==0 ) return;
   617         -    if( fossil_strcmp(zName, "logo-image")==0 ){
   618         -      Stmt ins;
   619         -      db_prepare(&ins,
   620         -        "REPLACE INTO config(name, value, mtime) VALUES(:name, :value, now())"
   621         -      );
   622         -      db_bind_text(&ins, ":name", zName);
   623         -      db_bind_blob(&ins, ":value", pContent);
   624         -      db_step(&ins);
   625         -      db_finalize(&ins);
   626         -    }else if( zName[0]=='@' ){
   627         -      /* Notice that we are evaluating arbitrary SQL received from the
   628         -      ** client.  But this can only happen if the client has authenticated
   629         -      ** as an administrator, so presumably we trust the client at this
   630         -      ** point.
   631         -      */
   632         -      db_multi_exec("%s", blob_str(pContent) /*safe-for-%s*/);
   633         -    }else{
   634         -      db_multi_exec(
   635         -         "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now())",
   636         -         zName, blob_str(pContent)
   637         -      );
   638         -    }
   639    439     }
   640    440   }
   641    441   
   642    442   /*
   643    443   ** Process a file full of "config" cards.
   644    444   */
   645    445   void configure_receive_all(Blob *pIn, int groupMask){
................................................................................
   755    555         );
   756    556         blob_appendf(pOut, "config /concealed %d\n%s\n",
   757    557                      blob_size(&rec), blob_str(&rec));
   758    558         nCard++;
   759    559         blob_reset(&rec);
   760    560       }
   761    561       db_finalize(&q);
          562  +  }
          563  +  if( groupMask & CONFIGSET_ALIAS ){
          564  +    db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
          565  +                   " WHERE name GLOB 'walias:/*' AND mtime>=%lld", iStart);
          566  +    while( db_step(&q)==SQLITE_ROW ){
          567  +      blob_appendf(&rec,"%s %s value %s",
          568  +        db_column_text(&q, 0),
          569  +        db_column_text(&q, 1),
          570  +        db_column_text(&q, 2)
          571  +      );
          572  +      blob_appendf(pOut, "config /config %d\n%s\n",
          573  +                   blob_size(&rec), blob_str(&rec));
          574  +      nCard++;
          575  +      blob_reset(&rec);
          576  +    }
          577  +    db_finalize(&q);
   762    578     }
   763    579     db_prepare(&q, "SELECT mtime, quote(name), quote(value) FROM config"
   764    580                    " WHERE name=:name AND mtime>=%lld", iStart);
   765    581     for(ii=0; ii<count(aConfig); ii++){
   766    582       if( (aConfig[ii].groupMask & groupMask)!=0 && aConfig[ii].zName[0]!='@' ){
   767    583         db_bind_text(&q, ":name", aConfig[ii].zName);
   768    584         while( db_step(&q)==SQLITE_ROW ){
................................................................................
   837    653   **
   838    654   ** Where METHOD is one of: export import merge pull push reset.  All methods
   839    655   ** accept the -R or --repository option to specify a repository.
   840    656   **
   841    657   **    %fossil configuration export AREA FILENAME
   842    658   **
   843    659   **         Write to FILENAME exported configuration information for AREA.
   844         -**         AREA can be one of:  all email project shun skin ticket user
          660  +**         AREA can be one of:  all email project shun skin ticket user alias
   845    661   **
   846    662   **    %fossil configuration import FILENAME
   847    663   **
   848    664   **         Read a configuration from FILENAME, overwriting the current
   849    665   **         configuration.
   850    666   **
   851    667   **    %fossil configuration merge FILENAME
................................................................................
   854    670   **         the current configuration.  Existing values take priority over
   855    671   **         values read from FILENAME.
   856    672   **
   857    673   **    %fossil configuration pull AREA ?URL?
   858    674   **
   859    675   **         Pull and install the configuration from a different server
   860    676   **         identified by URL.  If no URL is specified, then the default
   861         -**         server is used. Use the --legacy option for the older protocol
   862         -**         (when talking to servers compiled prior to 2011-04-27.)  Use
   863         -**         the --overwrite flag to completely replace local settings with
   864         -**         content received from URL.
          677  +**         server is used.  Use the --overwrite flag to completely
          678  +**         replace local settings with content received from URL.
   865    679   **
   866    680   **    %fossil configuration push AREA ?URL?
   867    681   **
   868    682   **         Push the local configuration into the remote server identified
   869    683   **         by URL.  Admin privilege is required on the remote server for
   870    684   **         this to work.  When the same record exists both locally and on
   871    685   **         the remote end, the one that was most recently changed wins.
   872         -**         Use the --legacy flag when talking to older servers.
   873    686   **
   874    687   **    %fossil configuration reset AREA
   875    688   **
   876    689   **         Restore the configuration to the default.  AREA as above.
   877    690   **
   878    691   **    %fossil configuration sync AREA ?URL?
   879    692   **
................................................................................
   930    743     }else
   931    744     if( strncmp(zMethod, "pull", n)==0
   932    745      || strncmp(zMethod, "push", n)==0
   933    746      || strncmp(zMethod, "sync", n)==0
   934    747     ){
   935    748       int mask;
   936    749       const char *zServer = 0;
   937         -    int legacyFlag = 0;
   938    750       int overwriteFlag = 0;
   939    751   
   940         -    if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
   941    752       if( strncmp(zMethod,"pull",n)==0 ){
   942    753         overwriteFlag = find_option("overwrite",0,0)!=0;
   943    754       }
   944    755       url_proxy_options();
   945    756       if( g.argc!=4 && g.argc!=5 ){
   946    757         usage(mprintf("%s AREA ?URL?", zMethod));
   947    758       }
................................................................................
   949    760       if( g.argc==5 ){
   950    761         zServer = g.argv[4];
   951    762       }
   952    763       url_parse(zServer, URL_PROMPT_PW);
   953    764       if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
   954    765       user_select();
   955    766       url_enable_proxy("via proxy: ");
   956         -    if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
   957    767       if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
   958    768       if( strncmp(zMethod, "push", n)==0 ){
   959    769         client_sync(0,0,(unsigned)mask);
   960    770       }else if( strncmp(zMethod, "pull", n)==0 ){
   961    771         client_sync(0,(unsigned)mask,0);
   962    772       }else{
   963    773         client_sync(0,(unsigned)mask,(unsigned)mask);

Changes to src/content.c.

   115    115     contentCache.szTotal = 0;
   116    116   }
   117    117   
   118    118   /*
   119    119   ** Return the srcid associated with rid.  Or return 0 if rid is
   120    120   ** original content and not a delta.
   121    121   */
   122         -static int findSrcid(int rid){
          122  +int delta_source_rid(int rid){
   123    123     static Stmt q;
   124    124     int srcid;
   125    125     db_static_prepare(&q, "SELECT srcid FROM delta WHERE rid=:rid");
   126    126     db_bind_int(&q, ":rid", rid);
   127    127     if( db_step(&q)==SQLITE_ROW ){
   128    128       srcid = db_column_int(&q, 0);
   129    129     }else{
................................................................................
   163    163       if( bag_find(&contentCache.available, rid) ){
   164    164         return 1;
   165    165       }
   166    166       if( content_size(rid, -1)<0 ){
   167    167         bag_insert(&contentCache.missing, rid);
   168    168         return 0;
   169    169       }
   170         -    srcid = findSrcid(rid);
          170  +    srcid = delta_source_rid(rid);
   171    171       if( srcid==0 ){
   172    172         bag_insert(&contentCache.available, rid);
   173    173         return 1;
   174    174       }
   175    175       rid = srcid;
   176    176     }
   177    177     fossil_panic("delta-loop in repository");
................................................................................
   248    248           blob_copy(pBlob, &contentCache.a[i].content);
   249    249           contentCache.a[i].age = contentCache.nextAge++;
   250    250           return 1;
   251    251         }
   252    252       }
   253    253     }
   254    254   
   255         -  nextRid = findSrcid(rid);
          255  +  nextRid = delta_source_rid(rid);
   256    256     if( nextRid==0 ){
   257    257       rc = content_of_blob(rid, pBlob);
   258    258     }else{
   259    259       int n = 1;
   260    260       int nAlloc = 10;
   261    261       int *a = 0;
   262    262       int mx;
................................................................................
   263    263       Blob delta, next;
   264    264   
   265    265       a = fossil_malloc( sizeof(a[0])*nAlloc );
   266    266       a[0] = rid;
   267    267       a[1] = nextRid;
   268    268       n = 1;
   269    269       while( !bag_find(&contentCache.inCache, nextRid)
   270         -        && (nextRid = findSrcid(nextRid))>0 ){
          270  +        && (nextRid = delta_source_rid(nextRid))>0 ){
   271    271         n++;
   272    272         if( n>=nAlloc ){
   273    273           if( n>db_int(0, "SELECT max(rid) FROM blob") ){
   274    274             fossil_panic("infinite loop in DELTA table");
   275    275           }
   276    276           nAlloc = nAlloc*2 + 10;
   277    277           a = fossil_realloc(a, nAlloc*sizeof(a[0]));
................................................................................
   713    713   }
   714    714   
   715    715   /*
   716    716   ** Make sure the content at rid is the original content and is not a
   717    717   ** delta.
   718    718   */
   719    719   void content_undelta(int rid){
   720         -  if( findSrcid(rid)>0 ){
          720  +  if( delta_source_rid(rid)>0 ){
   721    721       Blob x;
   722    722       if( content_get(rid, &x) ){
   723    723         Stmt s;
   724    724         db_prepare(&s, "UPDATE blob SET content=:c, size=%d WHERE rid=%d",
   725    725                        blob_size(&x), rid);
   726    726         blob_compress(&x, &x);
   727    727         db_bind_blob(&s, ":c", &x);
................................................................................
   770    770       "DELETE FROM private WHERE rid=:rid"
   771    771     );
   772    772     db_bind_int(&s1, ":rid", rid);
   773    773     db_exec(&s1);
   774    774   }
   775    775   
   776    776   /*
   777         -** Change the storage of rid so that it is a delta of srcid.
          777  +** Try to change the storage of rid so that it is a delta from one
          778  +** of the artifacts given in aSrc[0]..aSrc[nSrc-1].  The aSrc[*] that
          779  +** gives the smallest delta is choosen.
   778    780   **
   779    781   ** If rid is already a delta from some other place then no
   780         -** conversion occurs and this is a no-op unless force==1.
          782  +** conversion occurs and this is a no-op unless force==1.  If force==1,
          783  +** then nSrc must also be 1.
   781    784   **
   782    785   ** Never generate a delta that carries a private artifact into a public
   783    786   ** artifact.  Otherwise, when we go to send the public artifact on a
   784    787   ** sync operation, the other end of the sync will never be able to receive
   785    788   ** the source of the delta.  It is OK to delta private->private and
   786    789   ** public->private and public->public.  Just no private->public delta.
   787    790   **
   788         -** If srcid is a delta that depends on rid, then srcid is
   789         -** converted to undeltaed text.
          791  +** If aSrc[bestSrc] is already a dleta that depends on rid, then it is
          792  +** converted to undeltaed text before the aSrc[bestSrc]->rid delta is
          793  +** created, in order to prevent a delta loop.
   790    794   **
   791         -** If either rid or srcid contain less than 50 bytes, or if the
          795  +** If either rid or aSrc[i] contain less than 50 bytes, or if the
   792    796   ** resulting delta does not achieve a compression of at least 25%
   793    797   ** the rid is left untouched.
   794    798   **
   795    799   ** Return 1 if a delta is made and 0 if no delta occurs.
   796    800   */
   797         -int content_deltify(int rid, int srcid, int force){
          801  +int content_deltify(int rid, int *aSrc, int nSrc, int force){
   798    802     int s;
   799         -  Blob data, src, delta;
   800         -  Stmt s1, s2;
   801         -  int rc = 0;
          803  +  Blob data;           /* Content of rid */
          804  +  Blob src;            /* Content of aSrc[i] */
          805  +  Blob delta;          /* Delta from aSrc[i] to rid */
          806  +  Blob bestDelta;      /* Best delta seen so far */
          807  +  int bestSrc = 0;     /* Which aSrc is the source of the best delta */
          808  +  int rc = 0;          /* Value to return */
          809  +  int i;               /* Loop variable for aSrc[] */
   802    810   
   803         -  if( srcid==rid ) return 0;
   804         -  if( !force && findSrcid(rid)>0 ) return 0;
   805         -  if( content_is_private(srcid) && !content_is_private(rid) ){
   806         -    return 0;
   807         -  }
   808         -  s = srcid;
   809         -  while( (s = findSrcid(s))>0 ){
   810         -    if( s==rid ){
   811         -      content_undelta(srcid);
   812         -      break;
   813         -    }
   814         -  }
   815         -  content_get(srcid, &src);
   816         -  if( blob_size(&src)<50 ){
   817         -    blob_reset(&src);
   818         -    return 0;
   819         -  }
          811  +  /* If rid is already a child (a delta) of some other artifact, return
          812  +  ** immediately if the force flags is false
          813  +  */
          814  +  if( !force && delta_source_rid(rid)>0 ) return 0;
          815  +
          816  +  /* Get the complete content of the object to be delta-ed.  If the size
          817  +  ** is less than 50 bytes, then there really is no point in trying to do
          818  +  ** a delta, so return immediately
          819  +  */
   820    820     content_get(rid, &data);
   821    821     if( blob_size(&data)<50 ){
   822         -    blob_reset(&src);
          822  +    /* Do not try to create a delta for objects smaller than 50 bytes */
   823    823       blob_reset(&data);
   824    824       return 0;
   825    825     }
   826         -  blob_delta_create(&src, &data, &delta);
   827         -  if( blob_size(&delta) <= blob_size(&data)*0.75 ){
   828         -    blob_compress(&delta, &delta);
          826  +  blob_init(&bestDelta, 0, 0);
          827  +
          828  +  /* Loop over all candidate delta sources */
          829  +  for(i=0; i<nSrc; i++){
          830  +    int srcid = aSrc[i];
          831  +    if( srcid==rid ) continue;
          832  +    if( content_is_private(srcid) && !content_is_private(rid) ) continue;
          833  +
          834  +    /* Compute all ancestors of srcid and make sure rid is not one of them.
          835  +    ** If rid is an ancestor of srcid, then making rid a decendent of srcid
          836  +    ** would create a delta loop. */
          837  +    s = srcid;
          838  +    while( (s = delta_source_rid(s))>0 ){
          839  +      if( s==rid ){
          840  +        content_undelta(srcid);
          841  +        break;
          842  +      }
          843  +    }
          844  +    if( s!=0 ) continue;
          845  +
          846  +    content_get(srcid, &src);
          847  +    if( blob_size(&src)<50 ){
          848  +      /* The source is smaller then 50 bytes, so don't bother trying to use it*/
          849  +      blob_reset(&src);
          850  +      continue;
          851  +    }
          852  +    blob_delta_create(&src, &data, &delta);
          853  +    if( blob_size(&delta) < blob_size(&data)*0.75
          854  +     && (bestSrc<=0 || blob_size(&delta)<blob_size(&bestDelta))
          855  +    ){
          856  +      /* This is the best delta seen so far.  Remember it */
          857  +      blob_reset(&bestDelta);
          858  +      bestDelta = delta;
          859  +      bestSrc = srcid;
          860  +    }else{
          861  +      /* This delta is not a candidate for becoming the new parent of rid */
          862  +      blob_reset(&delta);
          863  +    }
          864  +    blob_reset(&src);
          865  +  }
          866  +
          867  +  /* If there is a winning candidate for the new parent of rid, then
          868  +  ** make that candidate the new parent now */
          869  +  if( bestSrc>0 ){
          870  +    Stmt s1, s2;  /* Statements used to create the delta */
          871  +    blob_compress(&bestDelta, &bestDelta);
   829    872       db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid);
   830         -    db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, srcid);
   831         -    db_bind_blob(&s1, ":data", &delta);
          873  +    db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, bestSrc);
          874  +    db_bind_blob(&s1, ":data", &bestDelta);
   832    875       db_begin_transaction();
   833    876       db_exec(&s1);
   834    877       db_exec(&s2);
   835    878       db_end_transaction(0);
   836    879       db_finalize(&s1);
   837    880       db_finalize(&s2);
   838    881       verify_before_commit(rid);
   839    882       rc = 1;
   840    883     }
   841         -  blob_reset(&src);
   842    884     blob_reset(&data);
   843         -  blob_reset(&delta);
          885  +  blob_reset(&bestDelta);
   844    886     return rc;
   845    887   }
   846    888   
   847    889   /*
   848    890   ** COMMAND: test-content-deltify
   849    891   **
   850         -** Convert the content at RID into a delta from SRCID.
          892  +** Usage:  %fossil RID SRCID SRCID ...  [-force]
          893  +**
          894  +** Convert the content at RID into a delta one of the from SRCIDs.
   851    895   */
   852    896   void test_content_deltify_cmd(void){
   853         -  if( g.argc!=5 ) usage("RID SRCID FORCE");
          897  +  int nSrc;
          898  +  int *aSrc;
          899  +  int i;
          900  +  int bForce = find_option("force",0,0)!=0;
          901  +  if( g.argc<3 ) usage("[--force] RID SRCID SRCID...");
          902  +  aSrc = fossil_malloc( (g.argc-2)*sizeof(aSrc[0]) );
          903  +  nSrc = 0;
          904  +  for(i=2; i<g.argc; i++) aSrc[nSrc++] = atoi(g.argv[i]);
   854    905     db_must_be_within_tree();
   855         -  content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
          906  +  content_deltify(atoi(g.argv[2]), aSrc, nSrc, bForce);
   856    907   }
   857    908   
   858    909   /*
   859    910   ** Return true if Blob p looks like it might be a parsable control artifact.
   860    911   */
   861    912   static int looks_like_control_artifact(Blob *p){
   862    913     const char *z = blob_buffer(p);

Changes to src/db.c.

  1473   1473     return 1;
  1474   1474   #endif
  1475   1475   }
  1476   1476   
  1477   1477   /*
  1478   1478   ** Returns non-zero if support for symlinks is currently enabled.
  1479   1479   */
  1480         -int db_allow_symlinks(int traversal){
  1481         -  if( traversal ){
  1482         -    if( g.allowSymlinks ) return 1;
  1483         -    return g.fNoDirSymlinks;
  1484         -  }else{
  1485         -    return g.allowSymlinks;
  1486         -  }
         1480  +int db_allow_symlinks(void){
         1481  +  return g.allowSymlinks;
  1487   1482   }
  1488   1483   
  1489   1484   /*
  1490   1485   ** Open the repository database given by zDbName.  If zDbName==NULL then
  1491   1486   ** get the name from the already open local database.
  1492   1487   */
  1493   1488   void db_open_repository(const char *zDbName){
................................................................................
  1807   1802   ** Return a pointer to a string that contains the RHS of an IN operator
  1808   1803   ** that will select CONFIG table names that are in the list of control
  1809   1804   ** settings.
  1810   1805   */
  1811   1806   const char *db_setting_inop_rhs(){
  1812   1807     Blob x;
  1813   1808     int i;
         1809  +  int nSetting;
         1810  +  const Setting *aSetting = setting_info(&nSetting);
  1814   1811     const char *zSep = "";
  1815   1812   
  1816   1813     blob_zero(&x);
  1817   1814     blob_append_sql(&x, "(");
  1818         -  for(i=0; aSetting[i].name; i++){
         1815  +  for(i=0; i<nSetting; i++){
  1819   1816       blob_append_sql(&x, "%s%Q", zSep/*safe-for-%s*/, aSetting[i].name);
  1820   1817       zSep = ",";
  1821   1818     }
  1822   1819     blob_append_sql(&x, ")");
  1823   1820     return blob_sql_text(&x);
  1824   1821   }
  1825   1822   
................................................................................
  1849   1846     char *zDate;
  1850   1847     Blob hash;
  1851   1848     Blob manifest;
  1852   1849   
  1853   1850     db_set("content-schema", CONTENT_SCHEMA, 0);
  1854   1851     db_set("aux-schema", AUX_SCHEMA_MAX, 0);
  1855   1852     db_set("rebuilt", get_version(), 0);
         1853  +  db_set("admin-log", "1", 0);
         1854  +  db_set("access-log", "1", 0);
  1856   1855     db_multi_exec(
  1857   1856         "INSERT INTO config(name,value,mtime)"
  1858   1857         " VALUES('server-code', lower(hex(randomblob(20))),now());"
  1859   1858         "INSERT INTO config(name,value,mtime)"
  1860   1859         " VALUES('project-code', lower(hex(randomblob(20))),now());"
  1861   1860     );
  1862   1861     if( !db_is_global("autosync") ) db_set_int("autosync", 1, 0);
................................................................................
  1871   1870     if( zTemplate ){
  1872   1871       /*
  1873   1872       ** Copy all settings from the supplied template repository.
  1874   1873       */
  1875   1874       db_multi_exec(
  1876   1875         "INSERT OR REPLACE INTO config"
  1877   1876         " SELECT name,value,mtime FROM settingSrc.config"
  1878         -      "  WHERE (name IN %s OR name IN %s)"
         1877  +      "  WHERE (name IN %s OR name IN %s OR name GLOB 'walias:/*')"
  1879   1878         "    AND name NOT GLOB 'project-*'"
  1880   1879         "    AND name NOT GLOB 'short-project-*';",
  1881   1880         configure_inop_rhs(CONFIGSET_ALL),
  1882   1881         db_setting_inop_rhs()
  1883   1882       );
  1884   1883       g.eHashPolicy = db_get_int("hash-policy", g.eHashPolicy);
  1885   1884       db_multi_exec(
................................................................................
  2736   2735         fossil_print("  (overridden by contents of file .fossil-settings/%s)\n",
  2737   2736                      pSetting->name);
  2738   2737       }
  2739   2738     }
  2740   2739     db_finalize(&q);
  2741   2740   }
  2742   2741   
  2743         -
  2744   2742   #if INTERFACE
  2745   2743   /*
  2746   2744   ** Define all settings, which can be controlled via the set/unset
  2747   2745   ** command.
  2748   2746   **
  2749   2747   ** var is the name of the internal configuration name for db_(un)set.
  2750   2748   ** If var is 0, the settings name is used.
................................................................................
  2761   2759     int width;            /* Width of display.  0 for boolean values. */
  2762   2760     int versionable;      /* Is this setting versionable? */
  2763   2761     int forceTextArea;    /* Force using a text area for display? */
  2764   2762     const char *def;      /* Default value */
  2765   2763   };
  2766   2764   #endif /* INTERFACE */
  2767   2765   
  2768         -const Setting aSetting[] = {
  2769         -  { "access-log",       0,              0, 0, 0, "off"                 },
  2770         -  { "admin-log",        0,              0, 0, 0, "off"                 },
         2766  +/*
         2767  +** SETTING: access-log      boolean default=off
         2768  +**
         2769  +** When the access-log setting is enabled, all login attempts (successful
         2770  +** and unsuccessful) on the web interface are recorded in the "access" table
         2771  +** of the repository.
         2772  +*/
         2773  +/*
         2774  +** SETTING: admin-log       boolean default=off
         2775  +**
         2776  +** When the admin-log setting is enabled, configuration changes are recorded
         2777  +** in the "admin_log" table of the repository.
         2778  +*/
  2771   2779   #if defined(_WIN32)
  2772         -  { "allow-symlinks",   0,              0, 1, 0, "off"                 },
  2773         -#else
  2774         -  { "allow-symlinks",   0,              0, 1, 0, "on"                  },
         2780  +/*
         2781  +** SETTING: allow-symlinks  boolean default=off versionable
         2782  +** Allows symbolic links in the repository when enabled.
         2783  +*/
         2784  +#endif
         2785  +#if !defined(_WIN32)
         2786  +/*
         2787  +** SETTING: allow-symlinks  boolean default=on versionable
         2788  +** Allows symbolic links in the repository when enabled.
         2789  +*/
         2790  +#endif
         2791  +/*
         2792  +** SETTING: auto-captcha    boolean default=on variable=autocaptcha
         2793  +** If enabled, the /login page provides a button that will automatically
         2794  +** fill in the captcha password.  This makes things easier for human users,
         2795  +** at the expense of also making logins easier for malecious robots.
         2796  +*/
         2797  +/*
         2798  +** SETTING: auto-hyperlink  boolean default=on
         2799  +** Use javascript to enable hyperlinks on web pages
         2800  +** for all users (regardless of the "h" privilege) if the
         2801  +** User-Agent string in the HTTP header look like it came
         2802  +** from real person, not a spider or bot.
         2803  +*/
         2804  +/*
         2805  +** SETTING: auto-shun       boolean default=on
         2806  +** If enabled, automatically pull the shunning list
         2807  +** from a server to which the client autosyncs.
         2808  +*/
         2809  +/*
         2810  +** SETTING: autosync        width=16 default=on
         2811  +** This setting can take either a boolean value or "pullonly"
         2812  +** If enabled, automatically pull prior to commit
         2813  +** or update and automatically push after commit or
         2814  +** tag or branch creation.  If the value is "pullonly"
         2815  +** then only pull operations occur automatically.
         2816  +*/
         2817  +/*
         2818  +** SETTING: autosync-tries  width=16 default=1
         2819  +** If autosync is enabled setting this to a value greater
         2820  +** than zero will cause autosync to try no more than this
         2821  +** number of attempts if there is a sync failure.
         2822  +*/
         2823  +/*
         2824  +** SETTING: binary-glob     width=40 versionable block-text
         2825  +** The VALUE of this setting is a comma or newline-separated list of
         2826  +** GLOB patterns that should be treated as binary files
         2827  +** for committing and merging purposes.  Example: *.jpg
         2828  +*/
         2829  +#if defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__)
         2830  +/*
         2831  +** SETTING: case-sensitive  boolean default=off
         2832  +** If TRUE, the files whose names differ only in case
         2833  +** are considered distinct.  If FALSE files whose names
         2834  +** differ only in case are the same file.  Defaults to
         2835  +** TRUE for unix and FALSE for Cygwin, Mac and Windows.
         2836  +*/
  2775   2837   #endif
  2776         -  { "auto-captcha",     "autocaptcha",  0, 0, 0, "on"                  },
  2777         -  { "auto-hyperlink",   0,              0, 0, 0, "on",                 },
  2778         -  { "auto-shun",        0,              0, 0, 0, "on"                  },
  2779         -  { "autosync",         0,              0, 0, 0, "on"                  },
  2780         -  { "autosync-tries",   0,             16, 0, 0, "1"                   },
  2781         -  { "binary-glob",      0,             40, 1, 0, ""                    },
  2782         -#if defined(_WIN32) || defined(__CYGWIN__) || defined(__DARWIN__) || \
  2783         -    defined(__APPLE__)
  2784         -  { "case-sensitive",   0,              0, 0, 0, "off"                 },
  2785         -#else
  2786         -  { "case-sensitive",   0,              0, 0, 0, "on"                  },
         2838  +#if !(defined(_WIN32)||defined(__CYGWIN__)||defined(__DARWIN__))
         2839  +/*
         2840  +** SETTING: case-sensitive  boolean default=on
         2841  +** If TRUE, the files whose names differ only in case
         2842  +** are considered distinct.  If FALSE files whose names
         2843  +** differ only in case are the same file.  Defaults to
         2844  +** TRUE for unix and FALSE for Cygwin, Mac and Windows.
         2845  +*/
  2787   2846   #endif
  2788         -  { "clean-glob",       0,             40, 1, 0, ""                    },
  2789         -  { "clearsign",        0,              0, 0, 0, "off"                 },
  2790         -  { "crlf-glob",        0,             40, 1, 0, ""                    },
  2791         -  { "crnl-glob",        0,             40, 1, 0, ""                    },
  2792         -  { "default-perms",    0,             16, 0, 0, "u"                   },
  2793         -  { "diff-binary",      0,              0, 0, 0, "on"                  },
  2794         -  { "diff-command",     0,             40, 0, 0, ""                    },
  2795         -  { "dont-push",        0,              0, 0, 0, "off"                 },
  2796         -  { "dotfiles",         0,              0, 1, 0, "off"                 },
  2797         -  { "editor",           0,             32, 0, 0, ""                    },
  2798         -  { "empty-dirs",       0,             40, 1, 0, ""                    },
  2799         -  { "encoding-glob",    0,             40, 1, 0, ""                    },
         2847  +/*
         2848  +** SETTING: clean-glob      width=40 versionable block-text
         2849  +** The VALUE of this setting is a comma or newline-separated list of GLOB
         2850  +** patterns specifying files that the "clean" command will
         2851  +** delete without prompting or allowing undo.
         2852  +** Example: *.a,*.lib,*.o
         2853  +*/
         2854  +/*
         2855  +** SETTING: clearsign       boolean default=off
         2856  +** When enabled, fossil will attempt to sign all commits
         2857  +** with gpg.  When disabled, commits will be unsigned.
         2858  +*/
         2859  +/*
         2860  +** SETTING: crlf-glob       width=40 versionable block-text
         2861  +** The value is a comma or newline-separated list of GLOB patterns for
         2862  +** text files in which it is ok to have CR, CR+LF or mixed
         2863  +** line endings. Set to "*" to disable CR+LF checking.
         2864  +** The crnl-glob setting is a compatibility alias.
         2865  +*/
         2866  +/*
         2867  +** SETTING: crnl-glob       width=40 versionable block-text
         2868  +** This is an alias for the crlf-glob setting
         2869  +*/
         2870  +/*
         2871  +** SETTING: default-perms   width=16 default=u
         2872  +** Permissions given automatically to new users.  For more
         2873  +** information on permissions see the Users page in Server
         2874  +** Administration of the HTTP UI.
         2875  +*/
         2876  +/* SETTING: diff-binary     boolean default=on
         2877  +** If enabled, permit files that may be binary
         2878  +** or that match the "binary-glob" setting to be used with
         2879  +** external diff programs.  If disabled, skip these files.
         2880  +*/
         2881  +/*
         2882  +** SETTING: diff-command    width=40
         2883  +** The value is an external command to run when performing a diff.
         2884  +** If undefined, the internal text diff will be used.
         2885  +*/
         2886  +/*
         2887  +** SETTING: dont-push       boolean default=off
         2888  +** If enabled, prevent this repository from pushing from client to
         2889  +** server.  This can be used as an extra precaution to prevent
         2890  +** accidental pushes to a public server from a private clone.
         2891  +*/
         2892  +/*
         2893  +** SETTING: dotfiles        boolean versionable default=off
         2894  +** If enabled, include --dotfiles option for all compatible commands.
         2895  +*/
         2896  +/*
         2897  +** SETTING: editor          width=32
         2898  +** The value is an external command that will launch the
         2899  +** text editor command used for check-in comments.
         2900  +*/
         2901  +/*
         2902  +** SETTING: empty-dirs      width=40 versionable block-text
         2903  +** The value is a comma or newline-separated list of pathnames. On
         2904  +** update and checkout commands, if no file or directory
         2905  +** exists with that name, an empty directory will be
         2906  +** created.
         2907  +*/
         2908  +/*
         2909  +** SETTING: encoding-glob   width=40 versionable block-text
         2910  +** The value is a comma or newline-separated list of GLOB
         2911  +** patterns specifying files that the "commit" command will
         2912  +** ignore when issuing warnings about text files that may
         2913  +** use another encoding than ASCII or UTF-8. Set to "*"
         2914  +** to disable encoding checking.
         2915  +*/
  2800   2916   #if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
  2801         -  { "exec-rel-paths",   0,              0, 0, 0, "on"                  },
  2802         -#else
  2803         -  { "exec-rel-paths",   0,              0, 0, 0, "off"                 },
         2917  +/*
         2918  +** SETTING: exec-rel-paths   boolean default=on
         2919  +** When executing certain external commands (e.g. diff and
         2920  +** gdiff), use relative paths.
         2921  +*/
         2922  +#endif
         2923  +#if !defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
         2924  +/*
         2925  +** SETTING: exec-rel-paths   boolean default=off
         2926  +** When executing certain external commands (e.g. diff and
         2927  +** gdiff), use relative paths.
         2928  +*/
  2804   2929   #endif
  2805         -  { "gdiff-command",    0,             40, 0, 0, "gdiff"               },
  2806         -  { "gmerge-command",   0,             40, 0, 0, ""                    },
  2807         -  { "hash-digits",      0,              5, 0, 0, "10"                  },
  2808         -  { "http-port",        0,             16, 0, 0, "8080"                },
  2809         -  { "https-login",      0,              0, 0, 0, "off"                 },
  2810         -  { "ignore-glob",      0,             40, 1, 0, ""                    },
  2811         -  { "keep-glob",        0,             40, 1, 0, ""                    },
  2812         -  { "localauth",        0,              0, 0, 0, "off"                 },
  2813         -  { "main-branch",      0,             40, 0, 0, "trunk"               },
  2814         -  { "manifest",         0,              5, 1, 0, ""                    },
  2815         -  { "max-loadavg",      0,             25, 0, 0, "0.0"                 },
  2816         -  { "max-upload",       0,             25, 0, 0, "250000"              },
  2817         -  { "mtime-changes",    0,              0, 0, 0, "on"                  },
         2930  +/*
         2931  +** SETTING: gdiff-command    width=40 default=gdiff
         2932  +** The value is an external command to run when performing a graphical
         2933  +** diff. If undefined, text diff will be used.
         2934  +*/
         2935  +/*
         2936  +** SETTING: gmerge-command   width=40
         2937  +** The value is a graphical merge conflict resolver command operating
         2938  +** on four files.  Examples:
         2939  +**
         2940  +**     kdiff3 "%baseline" "%original" "%merge" -o "%output"
         2941  +**     xxdiff "%original" "%baseline" "%merge" -M "%output"
         2942  +**     meld "%baseline" "%original" "%merge" "%output"
         2943  +*/
         2944  +/*
         2945  +** SETTING: hash-digits      width=5 default=10
         2946  +** The number of hexadecimal digits of the SHA3 hash to display.
         2947  +*/
         2948  +/*
         2949  +** SETTING: http-port        width=16 default=8080
         2950  +** The default TCP/IP port number to use by the "server"
         2951  +** and "ui" commands.
         2952  +*/
         2953  +/*
         2954  +** SETTING: https-login      boolean default=off
         2955  +** If true, then the Fossil web server will redirect unencrypted
         2956  +** login screeen requests to HTTPS.
         2957  +*/
         2958  +/*
         2959  +** SETTING: ignore-glob      width=40 versionable block-text
         2960  +** The value is a comma or newline-separated list of GLOB
         2961  +** patterns specifying files that the "add", "addremove",
         2962  +** "clean", and "extras" commands will ignore.
         2963  +**
         2964  +** Example:  *.log customCode.c notes.txt
         2965  +*/
         2966  +/*
         2967  +** SETTING: keep-glob        width=40 versionable block-text
         2968  +** The value is a comma or newline-separated list of GLOB
         2969  +** patterns specifying files that the "clean" command will keep
         2970  +*/
         2971  +/*
         2972  +** SETTING: localauth        boolean default=off
         2973  +** If enabled, require that HTTP connections from
         2974  +** 127.0.0.1 be authenticated by password.  If
         2975  +** false, all HTTP requests from localhost have
         2976  +** unrestricted access to the repository.
         2977  +*/
         2978  +/*
         2979  +** SETTING: main-branch      width=40 default=trunk
         2980  +** The value is the primary branch for the project.
         2981  +*/
         2982  +/*
         2983  +** SETTING: manifest         width=5 versionable
         2984  +** If enabled, automatically create files "manifest" and "manifest.uuid"
         2985  +** in every checkout.
         2986  +**
         2987  +** Optionally use combinations of characters 'r' for "manifest",
         2988  +** 'u' for "manifest.uuid" and 't' for "manifest.tags".  The SQLite
         2989  +** and Fossil repositories both require manifests.
         2990  +*/
         2991  +/*
         2992  +** SETTING: max-loadavg      width=25 default=0.0
         2993  +** Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
         2994  +** are disallowed if the system load average goes above this
         2995  +** value.  "0.0" means no limit.  This only works on unix.
         2996  +** Only local settings of this value make a difference since
         2997  +** when running as a web-server, Fossil does not open the
         2998  +** global configuration database.
         2999  +*/
         3000  +/*
         3001  +** SETTING: max-upload       width=25 default=250000
         3002  +** A limit on the size of uplink HTTP requests.
         3003  +*/
         3004  +/*
         3005  +** SETTING: mtime-changes    boolean default=on
         3006  +** Use file modification times (mtimes) to detect when
         3007  +** files have been modified.  If disabled, all managed files
         3008  +** are hashed to detect changes, which can be slow for large
         3009  +** projects.
         3010  +*/
  2818   3011   #if FOSSIL_ENABLE_LEGACY_MV_RM
  2819         -  { "mv-rm-files",      0,              0, 0, 0, "off"                 },
  2820         -#endif
  2821         -  { "pgp-command",      0,             40, 0, 0, "gpg --clearsign -o " },
  2822         -  { "proxy",            0,             32, 0, 0, "off"                 },
  2823         -  { "relative-paths",   0,              0, 0, 0, "on"                  },
  2824         -  { "repo-cksum",       0,              0, 0, 0, "on"                  },
  2825         -  { "self-register",    0,              0, 0, 0, "off"                 },
  2826         -  { "ssh-command",      0,             40, 0, 0, ""                    },
  2827         -  { "ssl-ca-location",  0,             40, 0, 0, ""                    },
  2828         -  { "ssl-identity",     0,             40, 0, 0, ""                    },
  2829         -#ifdef FOSSIL_ENABLE_TCL
  2830         -  { "tcl",              0,              0, 0, 0, "off"                 },
  2831         -  { "tcl-setup",        0,             40, 1, 1, ""                    },
         3012  +/*
         3013  +** SETTING: mv-rm-files      boolean default=off
         3014  +** If enabled, the "mv" and "rename" commands will also move
         3015  +** the associated files within the checkout -AND- the "rm"
         3016  +** and "delete" commands will also remove the associated
         3017  +** files from within the checkout.
         3018  +*/
  2832   3019   #endif
         3020  +/*
         3021  +** SETTING: pgp-command      width=40
         3022  +** Command used to clear-sign manifests at check-in.
         3023  +** Default value is "gpg --clearsign -o"
         3024  +*/
         3025  +/*
         3026  +** SETTING: proxy            width=32 default=off
         3027  +** URL of the HTTP proxy.  If undefined or "off" then
         3028  +** the "http_proxy" environment variable is consulted.
         3029  +** If the http_proxy environment variable is undefined
         3030  +** then a direct HTTP connection is used.
         3031  +*/
         3032  +/*
         3033  +** SETTING: relative-paths   boolean default=on
         3034  +** When showing changes and extras, report paths relative
         3035  +** to the current working directory.
         3036  +*/
         3037  +/*
         3038  +** SETTING: repo-cksum       boolean default=on
         3039  +** Compute checksums over all files in each checkout as a double-check
         3040  +** of correctness.  Disable this on large repositories for a performance
         3041  +** improvement.
         3042  +*/
         3043  +/*
         3044  +** SETTING: self-register    boolean default=off
         3045  +** Allow users to register themselves through the HTTP UI.
         3046  +** This is useful if you want to see other names than
         3047  +** "Anonymous" in e.g. ticketing system. On the other hand
         3048  +** users can not be deleted.
         3049  +*/
         3050  +/*
         3051  +** SETTING: ssh-command      width=40
         3052  +** The command used to talk to a remote machine with  the "ssh://" protocol.
         3053  +*/
         3054  +/*
         3055  +** SETTING: ssl-ca-location  width=40
         3056  +** The full pathname to a file containing PEM encoded
         3057  +** CA root certificates, or a directory of certificates
         3058  +** with filenames formed from the certificate hashes as
         3059  +** required by OpenSSL.
         3060  +**
         3061  +** If set, this will override the OS default list of
         3062  +** OpenSSL CAs. If unset, the default list will be used.
         3063  +** Some platforms may add additional certificates.
         3064  +** Checking your platform behaviour is required if the
         3065  +** exact contents of the CA root is critical for your
         3066  +** application.
         3067  +*/
         3068  +/*
         3069  +** SETTING: ssl-identity     width=40
         3070  +** The full pathname to a file containing a certificate
         3071  +** and private key in PEM format. Create by concatenating
         3072  +** the certificate and private key files.
         3073  +**
         3074  +** This identity will be presented to SSL servers to
         3075  +** authenticate this client, in addition to the normal
         3076  +** password authentication.
         3077  +*/
         3078  +#ifdef FOSSIL_ENABLE_TCL
         3079  +/*
         3080  +** SETTING: tcl              boolean default=off
         3081  +** If enabled Tcl integration commands will be added to the TH1
         3082  +** interpreter, allowing arbitrary Tcl expressions and
         3083  +** scripts to be evaluated from TH1.  Additionally, the Tcl
         3084  +** interpreter will be able to evaluate arbitrary TH1
         3085  +** expressions and scripts.
         3086  +*/
         3087  +/*
         3088  +** SETTING: tcl-setup        width=40 versionable block-text
         3089  +** This is the setup script to be evaluated after creating
         3090  +** and initializing the Tcl interpreter.  By default, this
         3091  +** is empty and no extra setup is performed.
         3092  +*/
         3093  +#endif /* FOSSIL_ENABLE_TCL */
  2833   3094   #ifdef FOSSIL_ENABLE_TH1_DOCS
  2834         -  { "th1-docs",         0,              0, 0, 0, "off"                 },
         3095  +/*
         3096  +** SETTING: th1-docs         boolean default=off
         3097  +** If enabled, this allows embedded documentation files to contain
         3098  +** arbitrary TH1 scripts that are evaluated on the server.  If native
         3099  +** Tcl integration is also enabled, this setting has the
         3100  +** potential to allow anybody with check-in privileges to
         3101  +** do almost anything that the associated operating system
         3102  +** user account could do.  Extreme caution should be used
         3103  +** when enabling this setting.
         3104  +*/
  2835   3105   #endif
  2836   3106   #ifdef FOSSIL_ENABLE_TH1_HOOKS
  2837         -  { "th1-hooks",        0,              0, 0, 0, "off"                 },
         3107  +/*
         3108  +** SETTING: th1-hooks        boolean default=off
         3109  +** If enabled, special TH1 commands will be called before and
         3110  +** after any Fossil command or web page.
         3111  +*/
  2838   3112   #endif
  2839         -  { "th1-setup",        0,             40, 1, 1, ""                    },
  2840         -  { "th1-uri-regexp",   0,             40, 1, 0, ""                    },
  2841         -  { "uv-sync",          0,              0, 0, 0, "off"                 },
  2842         -  { "web-browser",      0,             32, 0, 0, ""                    },
  2843         -  { 0,0,0,0,0,0 }
  2844         -};
         3113  +/*
         3114  +** SETTING: th1-setup        width=40 versionable block-text
         3115  +** This is the setup script to be evaluated after creating
         3116  +** and initializing the TH1 interpreter.  By default, this
         3117  +** is empty and no extra setup is performed.
         3118  +*/
         3119  +/*
         3120  +** SETTING: th1-uri-regexp   width=40 versionable block-text
         3121  +** Specify which URI's are allowed in HTTP requests from
         3122  +** TH1 scripts.  If empty, no HTTP requests are allowed
         3123  +** whatsoever.
         3124  +*/
         3125  +/*
         3126  +** SETTING: uv-sync          boolean default=off
         3127  +** If true, automatically send unversioned files as part
         3128  +** of a "fossil clone" or "fossil sync" command.  The
         3129  +** default is false, in which case the -u option is
         3130  +** needed to clone or sync unversioned files.
         3131  +*/
         3132  +/*
         3133  +** SETTING: web-browser      width=30
         3134  +** A shell command used to launch your preferred
         3135  +** web browser when given a URL as an argument.
         3136  +** Defaults to "start" on windows, "open" on Mac,
         3137  +** and "firefox" on Unix.
         3138  +*/
  2845   3139   
  2846   3140   /*
  2847   3141   ** Look up a control setting by its name.  Return a pointer to the Setting
  2848   3142   ** object, or NULL if there is no such setting.
  2849   3143   **
  2850   3144   ** If allowPrefix is true, then the Setting returned is the first one for
  2851   3145   ** which zName is a prefix of the Setting name.
  2852   3146   */
  2853         -const Setting *db_find_setting(const char *zName, int allowPrefix){
         3147  +Setting *db_find_setting(const char *zName, int allowPrefix){
  2854   3148     int lwr, mid, upr, c;
  2855   3149     int n = (int)strlen(zName) + !allowPrefix;
         3150  +  int nSetting;
         3151  +  const Setting *aSetting = setting_info(&nSetting);
  2856   3152     lwr = 0;
  2857         -  upr = count(aSetting)-2;
         3153  +  upr = nSetting - 1;
  2858   3154     while( upr>=lwr ){
  2859   3155       mid = (upr+lwr)/2;
  2860   3156       c = fossil_strncmp(zName, aSetting[mid].name, n);
  2861   3157       if( c<0 ){
  2862   3158         upr = mid - 1;
  2863   3159       }else if( c>0 ){
  2864   3160         lwr = mid + 1;
  2865   3161       }else{
  2866   3162         if( allowPrefix ){
  2867   3163           while( mid>lwr && fossil_strncmp(zName, aSetting[mid-1].name, n)==0 ){
  2868   3164             mid--;
  2869   3165           }
  2870   3166         }
  2871         -      return &aSetting[mid];
         3167  +      return (Setting*)&aSetting[mid];
  2872   3168       }
  2873   3169     }
  2874   3170     return 0;
  2875   3171   }
  2876   3172   
  2877   3173   /*
  2878   3174   ** COMMAND: settings
  2879   3175   ** COMMAND: unset*
  2880   3176   **
  2881         -** Usage: %fossil settings ?PROPERTY? ?VALUE? ?OPTIONS?
  2882         -**    or: %fossil unset PROPERTY ?OPTIONS?
         3177  +** Usage: %fossil settings ?SETTING? ?VALUE? ?OPTIONS?
         3178  +**    or: %fossil unset SETTING ?OPTIONS?
  2883   3179   **
  2884         -** The "settings" command with no arguments lists all properties and their
  2885         -** values.  With just a property name it shows the value of that property.
  2886         -** With a value argument it changes the property for the current repository.
         3180  +** The "settings" command with no arguments lists all settings and their
         3181  +** values.  With just a SETTING name it shows the current value of that setting.
         3182  +** With a VALUE argument it changes the property for the current repository.
  2887   3183   **
  2888   3184   ** Settings marked as versionable are overridden by the contents of the
  2889   3185   ** file named .fossil-settings/PROPERTY in the check-out root, if that
  2890   3186   ** file exists.
  2891   3187   **
  2892         -** The "unset" command clears a property setting.
         3188  +** The "unset" command clears a setting.
  2893   3189   **
  2894         -**
  2895         -**    access-log       If enabled, record successful and failed login attempts
  2896         -**                     in the "accesslog" table.  Default: off
  2897         -**
  2898         -**    admin-log        If enabled, record configuration changes in the
  2899         -**                     "admin_log" table.  Default: off
  2900         -**
  2901         -**    allow-symlinks   If enabled, don't follow symlinks, and instead treat
  2902         -**     (versionable)   them as symlinks on Unix. Has no effect on Windows
  2903         -**                     (existing links in repository created on Unix become
  2904         -**                     plain-text files with link destination path inside).
  2905         -**                     Default: on (Unix), off (Windows)
  2906         -**
  2907         -**    auto-captcha     If enabled, the Login page provides a button to
  2908         -**                     fill in the captcha password.  Default: on
  2909         -**
  2910         -**    auto-hyperlink   Use javascript to enable hyperlinks on web pages
  2911         -**                     for all users (regardless of the "h" privilege) if the
  2912         -**                     User-Agent string in the HTTP header look like it came
  2913         -**                     from real person, not a spider or bot.  Default: on
  2914         -**
  2915         -**    auto-shun        If enabled, automatically pull the shunning list
  2916         -**                     from a server to which the client autosyncs.
  2917         -**                     Default: on
  2918         -**
  2919         -**    autosync         If enabled, automatically pull prior to commit
  2920         -**                     or update and automatically push after commit or
  2921         -**                     tag or branch creation.  If the value is "pullonly"
  2922         -**                     then only pull operations occur automatically.
  2923         -**                     Default: on
  2924         -**
  2925         -**    autosync-tries   If autosync is enabled setting this to a value greater
  2926         -**                     than zero will cause autosync to try no more than this
  2927         -**                     number of attempts if there is a sync failure.
  2928         -**                     Default: 1
  2929         -**
  2930         -**    binary-glob      The VALUE is a comma or newline-separated list of
  2931         -**     (versionable)   GLOB patterns that should be treated as binary files
  2932         -**                     for committing and merging purposes.  Example: *.jpg
  2933         -**
  2934         -**    case-sensitive   If TRUE, the files whose names differ only in case
  2935         -**                     are considered distinct.  If FALSE files whose names
  2936         -**                     differ only in case are the same file.  Defaults to
  2937         -**                     TRUE for unix and FALSE for Cygwin, Mac and Windows.
  2938         -**
  2939         -**    clean-glob       The VALUE is a comma or newline-separated list of GLOB
  2940         -**     (versionable)   patterns specifying files that the "clean" command will
  2941         -**                     delete without prompting or allowing undo.
  2942         -**                     Example: *.a,*.lib,*.o
  2943         -**
  2944         -**    clearsign        When enabled, fossil will attempt to sign all commits
  2945         -**                     with gpg.  When disabled (the default), commits will
  2946         -**                     be unsigned.  Default: off
  2947         -**
  2948         -**    crlf-glob        A comma or newline-separated list of GLOB patterns for
  2949         -**     (versionable)   text files in which it is ok to have CR, CR+LF or mixed
  2950         -**                     line endings. Set to "*" to disable CR+LF checking.
  2951         -**                     The crnl-glob setting is a compatibility alias.
  2952         -**
  2953         -**    default-perms    Permissions given automatically to new users.  For more
  2954         -**                     information on permissions see Users page in Server
  2955         -**                     Administration of the HTTP UI. Default: u.
  2956         -**
  2957         -**    diff-binary      If TRUE (the default), permit files that may be binary
  2958         -**                     or that match the "binary-glob" setting to be used with
  2959         -**                     external diff programs.  If FALSE, skip these files.
  2960         -**
  2961         -**    diff-command     External command to run when performing a diff.
  2962         -**                     If undefined, the internal text diff will be used.
  2963         -**
  2964         -**    dont-push        Prevent this repository from pushing from client to
  2965         -**                     server.  Useful when setting up a private branch.
  2966         -**
  2967         -**    dotfiles         Include --dotfiles option for all compatible commands.
  2968         -**     (versionable)
  2969         -**
  2970         -**    editor           Text editor command used for check-in comments.
  2971         -**
  2972         -**    empty-dirs       A comma or newline-separated list of pathnames. On
  2973         -**     (versionable)   update and checkout commands, if no file or directory
  2974         -**                     exists with that name, an empty directory will be
  2975         -**                     created.
  2976         -**
  2977         -**    encoding-glob    The VALUE is a comma or newline-separated list of GLOB
  2978         -**     (versionable)   patterns specifying files that the "commit" command will
  2979         -**                     ignore when issuing warnings about text files that may
  2980         -**                     use another encoding than ASCII or UTF-8. Set to "*"
  2981         -**                     to disable encoding checking.
  2982         -**
  2983         -**    exec-rel-paths   When executing certain external commands (e.g. diff and
  2984         -**                     gdiff), use relative paths.
  2985         -**
  2986         -**    gdiff-command    External command to run when performing a graphical
  2987         -**                     diff. If undefined, text diff will be used.
  2988         -**
  2989         -**    gmerge-command   A graphical merge conflict resolver command operating
  2990         -**                     on four files.
  2991         -**                     Ex: kdiff3 "%baseline" "%original" "%merge" -o "%output"
  2992         -**                     Ex: xxdiff "%original" "%baseline" "%merge" -M "%output"
  2993         -**                     Ex: meld "%baseline" "%original" "%merge" "%output"
  2994         -**
  2995         -**    hash-digits      The number of hexadecimal digits of the SHA1 hash to
  2996         -**                     display.  (Default: 10; Minimum: 6)
  2997         -**
  2998         -**    http-port        The TCP/IP port number to use by the "server"
  2999         -**                     and "ui" commands.  Default: 8080
  3000         -**
  3001         -**    https-login      Send login credentials using HTTPS instead of HTTP
  3002         -**                     even if the login page request came via HTTP.
  3003         -**
  3004         -**    ignore-glob      The VALUE is a comma or newline-separated list of GLOB
  3005         -**     (versionable)   patterns specifying files that the "add", "addremove",
  3006         -**                     "clean", and "extra" commands will ignore.
  3007         -**                     Example:  *.log customCode.c notes.txt
  3008         -**
  3009         -**    keep-glob        The VALUE is a comma or newline-separated list of GLOB
  3010         -**     (versionable)   patterns specifying files that the "clean" command will
  3011         -**                     keep.
  3012         -**
  3013         -**    localauth        If enabled, require that HTTP connections from
  3014         -**                     127.0.0.1 be authenticated by password.  If
  3015         -**                     false, all HTTP requests from localhost have
  3016         -**                     unrestricted access to the repository.
  3017         -**
  3018         -**    main-branch      The primary branch for the project.  Default: trunk
  3019         -**
  3020         -**    manifest         If set to a true boolean value, automatically create
  3021         -**     (versionable)   files "manifest" and "manifest.uuid" in every checkout.
  3022         -**                     Optionally use combinations of characters 'r'
  3023         -**                     for "manifest", 'u' for "manifest.uuid" and 't' for
  3024         -**                     "manifest.tags".  The SQLite and Fossil repositories
  3025         -**                     both require manifests.  Default: off.
  3026         -**
  3027         -**    max-loadavg      Some CPU-intensive web pages (ex: /zip, /tarball, /blame)
  3028         -**                     are disallowed if the system load average goes above this
  3029         -**                     value.  "0.0" means no limit.  This only works on unix.
  3030         -**                     Only local settings of this value make a difference since
  3031         -**                     when running as a web-server, Fossil does not open the
  3032         -**                     global configuration database.
  3033         -**
  3034         -**    max-upload       A limit on the size of uplink HTTP requests.  The
  3035         -**                     default is 250000 bytes.
  3036         -**
  3037         -**    mtime-changes    Use file modification times (mtimes) to detect when
  3038         -**                     files have been modified.  (Default "on".)
  3039         -**
  3040         -**    mv-rm-files      If enabled (and Fossil was compiled with legacy "mv/rm"
  3041         -**                     support), the "mv" and "rename" commands will also move
  3042         -**                     the associated files within the checkout -AND- the "rm"
  3043         -**                     and "delete" commands will also remove the associated
  3044         -**                     files from within the checkout.  Default: off.
  3045         -**
  3046         -**    pgp-command      Command used to clear-sign manifests at check-in.
  3047         -**                     The default is "gpg --clearsign -o ".
  3048         -**
  3049         -**    proxy            URL of the HTTP proxy.  If undefined or "off" then
  3050         -**                     the "http_proxy" environment variable is consulted.
  3051         -**                     If the http_proxy environment variable is undefined
  3052         -**                     then a direct HTTP connection is used.
  3053         -**
  3054         -**    relative-paths   When showing changes and extras, report paths relative
  3055         -**                     to the current working directory.  Default: "on"
  3056         -**
  3057         -**    repo-cksum       Compute checksums over all files in each checkout
  3058         -**                     as a double-check of correctness.  Defaults to "on".
  3059         -**                     Disable on large repositories for a performance
  3060         -**                     improvement.
  3061         -**
  3062         -**    self-register    Allow users to register themselves through the HTTP UI.
  3063         -**                     This is useful if you want to see other names than
  3064         -**                     "Anonymous" in e.g. ticketing system. On the other hand
  3065         -**                     users can not be deleted. Default: off.
  3066         -**
  3067         -**    ssh-command      Command used to talk to a remote machine with
  3068         -**                     the "ssh://" protocol.
  3069         -**
  3070         -**    ssl-ca-location  The full pathname to a file containing PEM encoded
  3071         -**                     CA root certificates, or a directory of certificates
  3072         -**                     with filenames formed from the certificate hashes as
  3073         -**                     required by OpenSSL.
  3074         -**                     If set, this will override the OS default list of
  3075         -**                     OpenSSL CAs. If unset, the default list will be used.
  3076         -**                     Some platforms may add additional certificates.
  3077         -**                     Checking your platform behaviour is required if the
  3078         -**                     exact contents of the CA root is critical for your
  3079         -**                     application.
  3080         -**
  3081         -**    ssl-identity     The full pathname to a file containing a certificate
  3082         -**                     and private key in PEM format. Create by concatenating
  3083         -**                     the certificate and private key files.
  3084         -**                     This identity will be presented to SSL servers to
  3085         -**                     authenticate this client, in addition to the normal
  3086         -**                     password authentication.
  3087         -**
  3088         -**    tcl              If enabled (and Fossil was compiled with Tcl support),
  3089         -**                     Tcl integration commands will be added to the TH1
  3090         -**                     interpreter, allowing arbitrary Tcl expressions and
  3091         -**                     scripts to be evaluated from TH1.  Additionally, the Tcl
  3092         -**                     interpreter will be able to evaluate arbitrary TH1
  3093         -**                     expressions and scripts. Default: off.
  3094         -**
  3095         -**    tcl-setup        This is the setup script to be evaluated after creating
  3096         -**     (versionable)   and initializing the Tcl interpreter.  By default, this
  3097         -**                     is empty and no extra setup is performed.
  3098         -**
  3099         -**    th1-docs         WARNING: If enabled (and Fossil was compiled with TH1
  3100         -**                     support for embedded documentation files), this allows
  3101         -**                     embedded documentation files to contain arbitrary TH1
  3102         -**                     scripts that are evaluated on the server.  If native
  3103         -**                     Tcl integration is also enabled, this setting has the
  3104         -**                     potential to allow anybody with check-in privileges to
  3105         -**                     do almost anything that the associated operating system
  3106         -**                     user account could do.  Extreme caution should be used
  3107         -**                     when enabling this setting.  Default: off.
  3108         -**
  3109         -**    th1-hooks        If enabled (and Fossil was compiled with support for TH1
  3110         -**                     hooks), special TH1 commands will be called before and
  3111         -**                     after any Fossil command or web page. Default: off.
  3112         -**
  3113         -**    th1-setup        This is the setup script to be evaluated after creating
  3114         -**     (versionable)   and initializing the TH1 interpreter.  By default, this
  3115         -**                     is empty and no extra setup is performed.
  3116         -**
  3117         -**    th1-uri-regexp   Specify which URI's are allowed in HTTP requests from
  3118         -**     (versionable)   TH1 scripts.  If empty, no HTTP requests are allowed
  3119         -**                     whatsoever.  The default is an empty string.
  3120         -**
  3121         -**    uv-sync          If true, automatically send unversioned files as part
  3122         -**                     of a "fossil clone" or "fossil sync" command.  The
  3123         -**                     default is false, in which case the -u option is
  3124         -**                     needed to clone or sync unversioned files.
  3125         -**
  3126         -**    web-browser      A shell command used to launch your preferred
  3127         -**                     web browser when given a URL as an argument.
  3128         -**                     Defaults to "start" on windows, "open" on Mac,
  3129         -**                     and "firefox" on Unix.
         3190  +** Settings can have both a "local" repository-only value and "global" value
         3191  +** that applies to all repositories.  The local values are stored in the
         3192  +** "config" table of the repository and the global values are stored in the
         3193  +** $HOME/.fossil file on unix or in the %LOCALAPPDATA%/_fossil file on Windows.
         3194  +** If both a local and a global value exists for a setting, the local value
         3195  +** takes precedence.  This command normally operates on the local settings.
         3196  +** Use the --global option to change global settings.
  3130   3197   **
  3131   3198   ** Options:
  3132   3199   **   --global   set or unset the given property globally instead of
  3133   3200   **              setting or unsetting it for the open repository only.
  3134   3201   **
  3135   3202   **   --exact    only consider exact name matches.
  3136   3203   **
................................................................................
  3137   3204   ** See also: configuration
  3138   3205   */
  3139   3206   void setting_cmd(void){
  3140   3207     int i;
  3141   3208     int globalFlag = find_option("global","g",0)!=0;
  3142   3209     int exactFlag = find_option("exact",0,0)!=0;
  3143   3210     int unsetFlag = g.argv[1][0]=='u';
         3211  +  int nSetting;
         3212  +  const Setting *aSetting = setting_info(&nSetting);
  3144   3213     find_repository_option();
  3145   3214     verify_all_options();
  3146   3215     db_open_config(1, 0);
  3147   3216     if( !globalFlag ){
  3148   3217       db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
  3149   3218     }
  3150   3219     if( !g.repositoryOpen ){
  3151   3220       globalFlag = 1;
  3152   3221     }
  3153   3222     if( unsetFlag && g.argc!=3 ){
  3154   3223       usage("PROPERTY ?-global?");
  3155   3224     }
  3156   3225   
  3157         -  /* Verify that the aSetting[] entries are in sorted order.  This is
  3158         -  ** necessary for the binary search in db_find_setting() to work correctly.
  3159         -  */
  3160         -  for(i=1; aSetting[i].name; i++){
  3161         -    if( fossil_strcmp(aSetting[i-1].name, aSetting[i].name)>=0 ){
  3162         -      fossil_panic("Internal Error: aSetting[] entries for \"%s\""
  3163         -                   " and \"%s\" are out of order.",
  3164         -                   aSetting[i-1].name, aSetting[i].name);
  3165         -    }
  3166         -  }
  3167         -
  3168   3226     if( g.argc==2 ){
  3169         -    for(i=0; aSetting[i].name; i++){
         3227  +    for(i=0; i<nSetting; i++){
  3170   3228         print_setting(&aSetting[i]);
  3171   3229       }
  3172   3230     }else if( g.argc==3 || g.argc==4 ){
  3173   3231       const char *zName = g.argv[2];
  3174   3232       int n = (int)strlen(zName);
  3175   3233       const Setting *pSetting = db_find_setting(zName, !exactFlag);
  3176   3234       if( pSetting==0 ){

Changes to src/delta.c.

   569    569     int lenSrc,            /* Length of the source file */
   570    570     const char *zDelta,    /* Delta to apply to the pattern */
   571    571     int lenDelta,          /* Length of the delta */
   572    572     char *zOut             /* Write the output into this preallocated buffer */
   573    573   ){
   574    574     unsigned int limit;
   575    575     unsigned int total = 0;
   576         -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
          576  +#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
   577    577     char *zOrigOut = zOut;
   578    578   #endif
   579    579   
   580    580     limit = getInt(&zDelta, &lenDelta);
   581    581     if( *zDelta!='\n' ){
   582    582       /* ERROR: size integer not terminated by "\n" */
   583    583       return -1;
................................................................................
   626    626           zDelta += cnt;
   627    627           lenDelta -= cnt;
   628    628           break;
   629    629         }
   630    630         case ';': {
   631    631           zDelta++; lenDelta--;
   632    632           zOut[0] = 0;
   633         -#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
          633  +#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
   634    634           if( cnt!=checksum(zOrigOut, total) ){
   635    635             /* ERROR:  bad checksum */
   636    636             return -1;
   637    637           }
   638    638   #endif
   639    639           if( total!=limit ){
   640    640             /* ERROR: generated size does not match predicted size */

Changes to src/diff.c.

    39     39   #define DIFF_LINENO       ((u64)0x40000000) /* Show line numbers */
    40     40   #define DIFF_NUMSTAT      ((u64)0x80000000) /* Show line count of changes */
    41     41   #define DIFF_NOOPT        (((u64)0x01)<<32) /* Suppress optimizations (debug) */
    42     42   #define DIFF_INVERT       (((u64)0x02)<<32) /* Invert the diff (debug) */
    43     43   #define DIFF_CONTEXT_EX   (((u64)0x04)<<32) /* Use context even if zero */
    44     44   #define DIFF_NOTTOOBIG    (((u64)0x08)<<32) /* Only display if not too big */
    45     45   #define DIFF_STRIP_EOLCR  (((u64)0x10)<<32) /* Strip trailing CR */
    46         -#define DIFF_SLOW_SBS     (((u64)0x20)<<32) /* Better, but slower side-by-side */
           46  +#define DIFF_SLOW_SBS     (((u64)0x20)<<32) /* Better but slower side-by-side */
    47     47   
    48     48   /*
    49     49   ** These error messages are shared in multiple locations.  They are defined
    50     50   ** here for consistency.
    51     51   */
    52     52   #define DIFF_CANNOT_COMPUTE_BINARY \
    53     53       "cannot compute difference between binary files\n"
................................................................................
  2081   2081     struct AnnLine {  /* Lines of the original files... */
  2082   2082       const char *z;       /* The text of the line */
  2083   2083       short int n;         /* Number of bytes (omitting trailing \n) */
  2084   2084       short int iVers;     /* Level at which tag was set */
  2085   2085     } *aOrig;
  2086   2086     int nOrig;        /* Number of elements in aOrig[] */
  2087   2087     int nVers;        /* Number of versions analyzed */
  2088         -  int bLimit;       /* True if the iLimit was reached */
         2088  +  int bMoreToDo;    /* True if the limit was reached */
         2089  +  int origId;       /* RID for the zOrigin version */
         2090  +  int showId;       /* RID for the version being analyzed */
  2089   2091     struct AnnVers {
  2090   2092       const char *zFUuid;   /* File being analyzed */
  2091   2093       const char *zMUuid;   /* Check-in containing the file */
  2092   2094       const char *zDate;    /* Date of the check-in */
  2093   2095       const char *zBgColor; /* Suggested background color */
  2094   2096       const char *zUser;    /* Name of user who did the check-in */
  2095   2097       unsigned cnt;         /* Number of lines contributed by this check-in */
................................................................................
  2174   2176     /* Clear out the from file */
  2175   2177     free(p->c.aFrom);
  2176   2178   
  2177   2179     /* Return no errors */
  2178   2180     return 0;
  2179   2181   }
  2180   2182   
  2181         -
  2182         -/* Annotation flags (any DIFF flag can be used as Annotation flag as well) */
  2183         -#define ANN_FILE_VERS   (((u64)0x20)<<32) /* File vers not commit vers */
  2184         -#define ANN_FILE_ANCEST (((u64)0x40)<<32) /* Prefer checkins in the ANCESTOR */
         2183  +/* Return the current time as milliseconds since the Julian epoch */
         2184  +static sqlite3_int64 current_time_in_milliseconds(void){
         2185  +  static sqlite3_vfs *clockVfs = 0;
         2186  +  sqlite3_int64 t;
         2187  +  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
         2188  +  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
         2189  +    clockVfs->xCurrentTimeInt64(clockVfs, &t);
         2190  +  }else{
         2191  +    double r;
         2192  +    clockVfs->xCurrentTime(clockVfs, &r);
         2193  +    t = (sqlite3_int64)(r*86400000.0);
         2194  +  }
         2195  +  return t;
         2196  +}
  2185   2197   
  2186   2198   /*
  2187         -** Compute a complete annotation on a file.  The file is identified
  2188         -** by its filename number (filename.fnid) and check-in (mlink.mid).
         2199  +** Compute a complete annotation on a file.  The file is identified by its
         2200  +** filename and check-in name (NULL for current check-in).
  2189   2201   */
  2190   2202   static void annotate_file(
  2191         -  Annotator *p,        /* The annotator */
  2192         -  int fnid,            /* The name of the file to be annotated */
  2193         -  int mid,             /* Use the version of the file in this check-in */
  2194         -  int iLimit,          /* Limit the number of levels if greater than zero */
  2195         -  u64 annFlags         /* Flags to alter the annotation */
         2203  +  Annotator *p,          /* The annotator */
         2204  +  const char *zFilename, /* The name of the file to be annotated */
         2205  +  const char *zRevision, /* Use the version of the file in this check-in */
         2206  +  const char *zLimit,    /* Limit the number of versions analyzed */
         2207  +  const char *zOrigin,   /* The origin check-in, or NULL for root-of-tree */
         2208  +  u64 annFlags           /* Flags to alter the annotation */
  2196   2209   ){
  2197         -  Blob toAnnotate;     /* Text of the final (mid) version of the file */
  2198         -  Blob step;           /* Text of previous revision */
  2199         -  int rid;             /* Artifact ID of the file being annotated */
  2200         -  Stmt q;              /* Query returning all ancestor versions */
  2201         -  Stmt ins;            /* Inserts into the temporary VSEEN table */
  2202         -  int cnt = 0;         /* Number of versions examined */
  2203         -
  2204         -  /* Initialize the annotation */
  2205         -  rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
  2206         -  if( rid==0 ){
  2207         -    fossil_fatal("file #%d is unchanged in manifest #%d", fnid, mid);
  2208         -  }
  2209         -  if( !content_get(rid, &toAnnotate) ){
  2210         -    fossil_fatal("unable to retrieve content of artifact #%d", rid);
  2211         -  }
  2212         -  if( iLimit<=0 ) iLimit = 1000000000;
  2213         -  blob_to_utf8_no_bom(&toAnnotate, 0);
  2214         -  annotation_start(p, &toAnnotate, annFlags);
         2210  +  Blob toAnnotate;       /* Text of the final (mid) version of the file */
         2211  +  Blob step;             /* Text of previous revision */
         2212  +  Blob treename;         /* FILENAME translated to canonical form */
         2213  +  int cid;               /* Selected check-in ID */
         2214  +  int origid = 0;        /* The origin ID or zero */
         2215  +  int rid;               /* Artifact ID of the file being annotated */
         2216  +  int fnid;              /* Filename ID */
         2217  +  Stmt q;                /* Query returning all ancestor versions */
         2218  +  int cnt = 0;           /* Number of versions analyzed */
         2219  +  int iLimit;            /* Maximum number of versions to analyze */
         2220  +  sqlite3_int64 mxTime;  /* Halt at this time if not already complete */
         2221  +
         2222  +  if( zLimit ){
         2223  +    if( strcmp(zLimit,"none")==0 ){
         2224  +      iLimit = 0;
         2225  +      mxTime = 0;
         2226  +    }else if( sqlite3_strglob("*[0-9]s", zLimit)==0 ){
         2227  +      iLimit = 0;
         2228  +      mxTime = current_time_in_milliseconds() + 1000.0*atof(zLimit);
         2229  +    }else{
         2230  +      iLimit = atoi(zLimit);
         2231  +      if( iLimit<=0 ) iLimit = 30;
         2232  +      mxTime = 0;
         2233  +    }
         2234  +  }else{
         2235  +    /* Default limit is as much as we can do in 1.000 seconds */
         2236  +    iLimit = 0;
         2237  +    mxTime = current_time_in_milliseconds()+1000;
         2238  +  }
  2215   2239     db_begin_transaction();
  2216         -  db_multi_exec(
  2217         -     "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);"
  2218         -     "DELETE FROM vseen;"
         2240  +
         2241  +  /* Get the artificate ID for the check-in begin analyzed */
         2242  +  if( zRevision ){
         2243  +    cid = name_to_typed_rid(zRevision, "ci");
         2244  +  }else{
         2245  +    db_must_be_within_tree();
         2246  +    cid = db_lget_int("checkout", 0);
         2247  +  }
         2248  +  origid = zOrigin ? name_to_typed_rid(zOrigin, "ci") : 0;
         2249  +
         2250  +  /* Compute all direct ancestors of the check-in being analyzed into
         2251  +  ** the "ancestor" table. */
         2252  +  if( origid ){
         2253  +    path_shortest_stored_in_ancestor_table(origid, cid);
         2254  +  }else{
         2255  +    compute_direct_ancestors(cid);
         2256  +  }
         2257  +
         2258  +  /* Get filename ID */
         2259  +  file_tree_name(zFilename, &treename, 0, 1);
         2260  +  zFilename = blob_str(&treename);
         2261  +  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
         2262  +
         2263  +  db_prepare(&q,
         2264  +    "SELECT DISTINCT"
         2265  +    "   (SELECT uuid FROM blob WHERE rid=mlink.fid),"
         2266  +    "   (SELECT uuid FROM blob WHERE rid=mlink.mid),"
         2267  +    "   date(event.mtime),"
         2268  +    "   coalesce(event.euser,event.user),"
         2269  +    "   mlink.fid"
         2270  +    "  FROM mlink, event, ancestor"
         2271  +    " WHERE mlink.fnid=%d"
         2272  +    "   AND ancestor.rid=mlink.mid"
         2273  +    "   AND event.objid=mlink.mid"
         2274  +    "   AND mlink.mid!=mlink.pid"
         2275  +    " ORDER BY ancestor.generation;",
         2276  +    fnid
  2219   2277     );
  2220   2278   
  2221         -  db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)");
  2222         -  db_prepare(&q,
  2223         -    "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid),"
  2224         -    "       (SELECT uuid FROM blob WHERE rid=mlink.mid),"
  2225         -    "       date(event.mtime),"
  2226         -    "       coalesce(event.euser,event.user),"
  2227         -    "       mlink.pid"
  2228         -    "  FROM mlink, event"
  2229         -    " WHERE mlink.fid=:rid"
  2230         -    "   AND event.objid=mlink.mid"
  2231         -    "   AND mlink.pid NOT IN vseen"
  2232         -    " ORDER BY %s event.mtime",
  2233         -    (annFlags & ANN_FILE_ANCEST)!=0 ?
  2234         -         "(mlink.mid IN (SELECT rid FROM ancestor)) DESC,":""
  2235         -  );
  2236         -
  2237         -  db_bind_int(&q, ":rid", rid);
  2238         -  if( iLimit==0 ) iLimit = 1000000000;
  2239         -  while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){
  2240         -    int prevId = db_column_int(&q, 4);
         2279  +  while( db_step(&q)==SQLITE_ROW ){
         2280  +    if( cnt>=3 ){  /* Process at least 3 rows before imposing limits */
         2281  +      if( (iLimit>0 && cnt>=iLimit)
         2282  +       || (cnt>0 && mxTime>0 && current_time_in_milliseconds()>mxTime)
         2283  +      ){
         2284  +        p->bMoreToDo = 1;
         2285  +        break;
         2286  +      }
         2287  +    }
         2288  +    rid = db_column_int(&q, 4);
         2289  +    if( cnt==0 ){
         2290  +      if( !content_get(rid, &toAnnotate) ){
         2291  +        fossil_fatal("unable to retrieve content of artifact #%d", rid);
         2292  +      }
         2293  +      blob_to_utf8_no_bom(&toAnnotate, 0);
         2294  +      annotation_start(p, &toAnnotate, annFlags);
         2295  +      p->bMoreToDo = origid!=0;
         2296  +      p->origId = origid;
         2297  +      p->showId = cid;
         2298  +    }
  2241   2299       p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0]));
  2242   2300       p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0));
  2243   2301       p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
  2244   2302       p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
  2245   2303       p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
  2246         -    if( p->nVers ){
         2304  +    if( cnt>0 ){
  2247   2305         content_get(rid, &step);
  2248   2306         blob_to_utf8_no_bom(&step, 0);
  2249   2307         annotation_step(p, &step, p->nVers-1, annFlags);
  2250   2308         blob_reset(&step);
  2251   2309       }
  2252   2310       p->nVers++;
  2253         -    db_bind_int(&ins, ":rid", rid);
  2254         -    db_step(&ins);
  2255         -    db_reset(&ins);
  2256         -    db_reset(&q);
  2257         -    rid = prevId;
  2258         -    db_bind_int(&q, ":rid", prevId);
  2259   2311       cnt++;
  2260   2312     }
  2261         -  p->bLimit = iLimit==cnt;
  2262   2313     db_finalize(&q);
  2263         -  db_finalize(&ins);
  2264   2314     db_end_transaction(0);
  2265   2315   }
  2266   2316   
  2267   2317   /*
  2268   2318   ** Return a color from a gradient.
  2269   2319   */
  2270   2320   unsigned gradient_color(unsigned c1, unsigned c2, int n, int i){
................................................................................
  2293   2343   ** URL: /blame?checkin=ID&filename=FILENAME
  2294   2344   ** URL: /praise?checkin=ID&filename=FILENAME
  2295   2345   **
  2296   2346   ** Show the most recent change to each line of a text file.  /annotate shows
  2297   2347   ** the date of the changes and the check-in hash (with a link to the
  2298   2348   ** check-in).  /blame and /praise also show the user who made the check-in.
  2299   2349   **
         2350  +** Reverse Annotations:  Normally, these web pages look at versions of
         2351  +** FILENAME moving backwards in time back toward the root check-in.  However,
         2352  +** if the origin= query parameter is used to specify some future check-in
         2353  +** (example: "origin=trunk") then these pages show changes moving towards
         2354  +** that alternative origin.  Thus using "origin=trunk" on an historical
         2355  +** version of the file shows the first time each line in the file was been
         2356  +** changed in subsequent check-ins.
         2357  +**
  2300   2358   ** Query parameters:
  2301   2359   **
  2302         -**    checkin=ID          The manifest ID at which to start the annotation
         2360  +**    checkin=ID          The check-in at which to start the annotation
  2303   2361   **    filename=FILENAME   The filename.
  2304         -**    filevers            Show file versions rather than check-in versions
  2305         -**    limit=N             Limit the search depth to N ancestors
         2362  +**    filevers=BOOLEAN    Show file versions rather than check-in versions
         2363  +**    limit=LIMIT         Limit the amount of analysis:
         2364  +**                           "none"  No limit
         2365  +**                           "Xs"    As much as can be computed in X seconds
         2366  +**                           "N"     N versions
  2306   2367   **    log=BOOLEAN         Show a log of versions analyzed
  2307         -**    w                   Ignore whitespace
         2368  +**    origin=ID           The origin checkin.  If unspecified, the root
         2369  +**                           check-in over the entire repository is used.
         2370  +**                           Specify "origin=trunk" or similar for a reverse
         2371  +**                           annotation
         2372  +**    w=BOOLEAN           Ignore whitespace
  2308   2373   **
  2309   2374   */
  2310   2375   void annotation_page(void){
  2311         -  int mid;
  2312         -  int fnid;
  2313   2376     int i;
  2314         -  int iLimit;            /* Depth limit */
  2315         -  u64 annFlags = (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR);
  2316         -  int showLog = 0;       /* True to display the log */
  2317         -  int ignoreWs = 0;      /* Ignore whitespace */
         2377  +  const char *zLimit;    /* Depth limit */
         2378  +  u64 annFlags = DIFF_STRIP_EOLCR;
         2379  +  int showLog;           /* True to display the log */
         2380  +  int fileVers;          /* Show file version instead of check-in versions */
         2381  +  int ignoreWs;          /* Ignore whitespace */
  2318   2382     const char *zFilename; /* Name of file to annotate */
         2383  +  const char *zRevision; /* Name of check-in from which to start annotation */
  2319   2384     const char *zCI;       /* The check-in containing zFilename */
         2385  +  const char *zOrigin;   /* The origin of the analysis */
         2386  +  int szHash;            /* Number of characters in %S display */
         2387  +  char *zLink;
  2320   2388     Annotator ann;
  2321   2389     HQuery url;
  2322   2390     struct AnnVers *p;
  2323   2391     unsigned clr1, clr2, clr;
  2324   2392     int bBlame = g.zPath[0]!='a';/* True for BLAME output.  False for ANNOTATE. */
  2325   2393   
  2326   2394     /* Gather query parameters */
  2327         -  showLog = atoi(PD("log","1"));
  2328   2395     login_check_credentials();
  2329   2396     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  2330   2397     if( exclude_spiders() ) return;
  2331   2398     load_control();
  2332         -  mid = name_to_typed_rid(PD("checkin","0"),"ci");
  2333   2399     zFilename = P("filename");
  2334         -  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
  2335         -  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  2336         -  iLimit = atoi(PD("limit","20"));
  2337         -  if( P("filevers") ) annFlags |= ANN_FILE_VERS;
  2338         -  ignoreWs = P("w")!=0;
         2400  +  zRevision = PD("checkin",0);
         2401  +  zOrigin = P("origin");
         2402  +  zLimit = P("limit");
         2403  +  showLog = PB("log");
         2404  +  fileVers = PB("filevers");
         2405  +  ignoreWs = PB("w");
  2339   2406     if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS;
  2340         -  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
  2341         -    fossil_redirect_home();
  2342         -  }
  2343   2407   
  2344   2408     /* compute the annotation */
  2345         -  compute_direct_ancestors(mid);
  2346         -  annotate_file(&ann, fnid, mid, iLimit, annFlags);
         2409  +  annotate_file(&ann, zFilename, zRevision, zLimit, zOrigin, annFlags);
  2347   2410     zCI = ann.aVers[0].zMUuid;
  2348   2411   
  2349   2412     /* generate the web page */
  2350   2413     style_header("Annotation For %h", zFilename);
  2351   2414     if( bBlame ){
  2352   2415       url_initialize(&url, "blame");
  2353   2416     }else{
  2354   2417       url_initialize(&url, "annotate");
  2355   2418     }
  2356   2419     url_add_parameter(&url, "checkin", P("checkin"));
  2357   2420     url_add_parameter(&url, "filename", zFilename);
  2358         -  if( iLimit!=20 ){
  2359         -    url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit));
         2421  +  if( zLimit ){
         2422  +    url_add_parameter(&url, "limit", zLimit);
  2360   2423     }
         2424  +  url_add_parameter(&url, "w", ignoreWs ? "1" : "0");
  2361   2425     url_add_parameter(&url, "log", showLog ? "1" : "0");
  2362         -  if( ignoreWs ){
  2363         -    url_add_parameter(&url, "w", "");
  2364         -    style_submenu_element("Show Whitespace Changes", "%s",
  2365         -        url_render(&url, "w", 0, 0, 0));
  2366         -  }else{
  2367         -    style_submenu_element("Ignore Whitespace", "%s",
  2368         -        url_render(&url, "w", "", 0, 0));
  2369         -  }
  2370         -  if( showLog ){
  2371         -    style_submenu_element("Hide Log", "%s", url_render(&url, "log", "0", 0, 0));
  2372         -  }else{
  2373         -    style_submenu_element("Show Log", "%s", url_render(&url, "log", "1", 0, 0));
  2374         -  }
  2375         -  if( ann.bLimit ){
  2376         -    char *z1, *z2;
         2426  +  url_add_parameter(&url, "filevers", fileVers ? "1" : "0");
         2427  +  style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
         2428  +  style_submenu_checkbox("log", "Log", 0, "toggle_annotation_log()");
         2429  +  style_submenu_checkbox("filevers", "Link to Files", 0, 0);
         2430  +  if( ann.bMoreToDo ){
  2377   2431       style_submenu_element("All Ancestors", "%s",
  2378         -       url_render(&url, "limit", "-1", 0, 0));
  2379         -    z1 = sqlite3_mprintf("%d Ancestors", iLimit+20);
  2380         -    z2 = sqlite3_mprintf("%d", iLimit+20);
  2381         -    style_submenu_element(z1, "%s", url_render(&url, "limit", z2, 0, 0));
  2382         -  }
  2383         -  if( iLimit>20 ){
  2384         -    style_submenu_element("20 Ancestors", "%s",
  2385         -       url_render(&url, "limit", "20", 0, 0));
         2432  +       url_render(&url, "limit", "none", 0, 0));
  2386   2433     }
  2387   2434     if( skin_detail_boolean("white-foreground") ){
  2388   2435       clr1 = 0xa04040;
  2389   2436       clr2 = 0x4059a0;
  2390   2437     }else{
  2391   2438       clr1 = 0xffb5b5;  /* Recent changes: red (hot) */
  2392   2439       clr2 = 0xb5e0ff;  /* Older changes: blue (cold) */
  2393   2440     }
  2394   2441     for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
  2395   2442       clr = gradient_color(clr1, clr2, ann.nVers-1, i);
  2396   2443       ann.aVers[i].zBgColor = mprintf("#%06x", clr);
  2397   2444     }
  2398   2445   
  2399         -  if( showLog ){
  2400         -    char *zLink = href("%R/finfo?name=%t&ci=%!S",zFilename,zCI);
  2401         -    @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
  2402         -    @ <ol>
  2403         -    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
  2404         -      @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
  2405         -      @ check-in %z(href("%R/info/%!S",p->zMUuid))%S(p->zMUuid)</a>
  2406         -      @ artifact %z(href("%R/artifact/%!S",p->zFUuid))%S(p->zFUuid)</a>
  2407         -      @ </span>
  2408         -#if 0
  2409         -      if( i>0 ){
  2410         -        char *zLink = xhref("target='infowindow'",
  2411         -                            "%R/fdiff?v1=%S&v2=%S&sbs=1",
  2412         -                            p->zFUuid,ann.aVers[0].zFUuid);
  2413         -        @ %z(zLink)[diff-to-top]</a>
  2414         -        if( i>1 ){
  2415         -           zLink = xhref("target='infowindow'",
  2416         -                         "%R/fdiff?v1=%S&v2=%S&sbs=1",
  2417         -                         p->zFUuid,p[-1].zFUuid);
  2418         -           @ %z(zLink)[diff-to-previous]</a>
  2419         -        }
  2420         -      }
  2421         -#endif
  2422         -    }
  2423         -    @ </ol>
  2424         -    @ <hr />
         2446  +  @ <div id="annotation_log" style='display:%s(showLog?"block":"none");'>
         2447  +  if( zOrigin ){
         2448  +    zLink = href("%R/finfo?name=%t&ci=%!S&orig=%!S",zFilename,zCI,zOrigin);
         2449  +  }else{
         2450  +    zLink = href("%R/finfo?name=%t&ci=%!S",zFilename,zCI);
         2451  +  }
         2452  +  @ <h2>Versions of %z(zLink)%h(zFilename)</a> analyzed:</h2>
         2453  +  @ <ol>
         2454  +  for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
         2455  +    @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
         2456  +    @ check-in %z(href("%R/info/%!S",p->zMUuid))%S(p->zMUuid)</a>
         2457  +    @ artifact %z(href("%R/artifact/%!S",p->zFUuid))%S(p->zFUuid)</a>
         2458  +    @ </span>
  2425   2459     }
  2426         -  if( !ann.bLimit ){
         2460  +  @ </ol>
         2461  +  @ <hr />
         2462  +  @ </div>
         2463  +  @ <script>
         2464  +  @ function toggle_annotation_log(){
         2465  +  @   var w = gebi("annotation_log");
         2466  +  @   var x = document.forms["f01"].elements["log"].checked
         2467  +  @   w.style.display = x ? "block" : "none";
         2468  +  @ }
         2469  +  @ </script>
         2470  +
         2471  +  if( !ann.bMoreToDo ){
         2472  +    assert( ann.origId==0 );  /* bMoreToDo always set for a point-to-point */
  2427   2473       @ <h2>Origin for each line in
  2428   2474       @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a>
  2429   2475       @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2>
  2430         -    iLimit = ann.nVers+10;
         2476  +  }else if( ann.origId>0 ){
         2477  +    @ <h2>Lines of
         2478  +    @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a>
         2479  +    @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>
         2480  +    @ that are changed by the sequence of edits moving toward
         2481  +    @ check-in %z(href("%R/info/%!S",zOrigin))%S(zOrigin)</a>:</h2>
  2431   2482     }else{
  2432         -    @ <h2>Lines added by the %d(iLimit) most recent ancestors of
         2483  +    @ <h2>Lines added by the %d(ann.nVers) most recent ancestors of
  2433   2484       @ %z(href("%R/finfo?name=%h&ci=%!S", zFilename, zCI))%h(zFilename)</a>
  2434   2485       @ from check-in %z(href("%R/info/%!S",zCI))%S(zCI)</a>:</h2>
  2435   2486     }
  2436   2487     @ <pre>
         2488  +  szHash = 10;
  2437   2489     for(i=0; i<ann.nOrig; i++){
  2438   2490       int iVers = ann.aOrig[i].iVers;
  2439   2491       char *z = (char*)ann.aOrig[i].z;
  2440   2492       int n = ann.aOrig[i].n;
  2441   2493       char zPrefix[300];
  2442   2494       z[n] = 0;
  2443         -    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
         2495  +    if( iVers<0 && !ann.bMoreToDo ) iVers = ann.nVers-1;
  2444   2496   
  2445   2497       if( bBlame ){
  2446   2498         if( iVers>=0 ){
  2447   2499           struct AnnVers *p = ann.aVers+iVers;
  2448         -        char *zLink = xhref("target='infowindow'", "%R/info/%!S", p->zMUuid);
         2500  +        const char *zUuid = fileVers ? p->zFUuid : p->zMUuid;
         2501  +        char *zLink = xhref("target='infowindow'", "%R/info/%!S", zUuid);
  2449   2502           sqlite3_snprintf(sizeof(zPrefix), zPrefix,
  2450   2503                "<span style='background-color:%s'>"
  2451   2504                "%s%.10s</a> %s</span> %13.13s:",
  2452         -             p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
         2505  +             p->zBgColor, zLink, zUuid, p->zDate, p->zUser);
  2453   2506           fossil_free(zLink);
  2454   2507         }else{
  2455         -        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
         2508  +        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%*s", szHash+26, "");
  2456   2509         }
  2457   2510       }else{
  2458   2511         if( iVers>=0 ){
  2459   2512           struct AnnVers *p = ann.aVers+iVers;
  2460         -        char *zLink = xhref("target='infowindow'", "%R/info/%!S", p->zMUuid);
         2513  +        const char *zUuid = fileVers ? p->zFUuid : p->zMUuid;
         2514  +        char *zLink = xhref("target='infowindow'", "%R/info/%!S", zUuid);
  2461   2515           sqlite3_snprintf(sizeof(zPrefix), zPrefix,
  2462   2516                "<span style='background-color:%s'>"
  2463   2517                "%s%.10s</a> %s</span> %4d:",
  2464         -             p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
         2518  +             p->zBgColor, zLink, zUuid, p->zDate, i+1);
  2465   2519           fossil_free(zLink);
  2466   2520         }else{
  2467         -        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1);
         2521  +        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%*s%4d:",szHash+12,"",i+1);
  2468   2522         }
  2469   2523       }
  2470   2524       @ %s(zPrefix) %h(z)
  2471   2525   
  2472   2526     }
  2473   2527     @ </pre>
  2474   2528     style_footer();
................................................................................
  2475   2529   }
  2476   2530   
  2477   2531   /*
  2478   2532   ** COMMAND: annotate
  2479   2533   ** COMMAND: blame
  2480   2534   ** COMMAND: praise
  2481   2535   **
  2482         -** Usage: %fossil (annotate|blame|praise) ?OPTIONS? FILENAME
         2536  +** Usage: %fossil annotate|blame|praise ?OPTIONS? FILENAME
         2537  +**
         2538  +** Output the text of a file with markings to show when each line of the file
         2539  +** was last modified.  The version currently checked out is shown by default.
         2540  +** Other versions may be specified using the -r option.  The "annotate" command
         2541  +** shows line numbers and omits the username.  The "blame" and "praise" commands
         2542  +** show the user who made each check-in.
  2483   2543   **
  2484         -** Output the text of a file with markings to show when each line of
  2485         -** the file was last modified.  The "annotate" command shows line numbers
  2486         -** and omits the username.  The "blame" and "praise" commands show the user
  2487         -** who made each check-in and omits the line number.
         2544  +** Reverse Annotations:  Normally, these commands look at versions of
         2545  +** FILENAME moving backwards in time back toward the root check-in, and
         2546  +** thus the output shows the most recent change to each line.  However,
         2547  +** if the -o|--origin option is used to specify some future check-in
         2548  +** (example: "-o trunk") then these commands show changes moving towards
         2549  +** that alternative origin.  Thus using "-o trunk" on an historical version
         2550  +** of the file shows the first time each line in the file was been changed
         2551  +** by subsequent check-ins.
  2488   2552   **
  2489   2553   ** Options:
  2490   2554   **   --filevers                  Show file version numbers rather than
  2491   2555   **                               check-in versions
         2556  +**   -r|--revision VERSION       The specific check-in containing the file
  2492   2557   **   -l|--log                    List all versions analyzed
  2493         -**   -n|--limit N                Only look backwards in time by N versions
         2558  +**   -n|--limit LIMIT            Limit the amount of analysis:
         2559  +**                                 N      Up to N versions
         2560  +**                                 Xs     As much as possible in X seconds
         2561  +**                                 none   No limit
         2562  +**   -o|--origin VERSION         The origin check-in. By default this is the
         2563  +**                                 root of the repository. Set to "trunk" or
         2564  +**                                 similar for a reverse annotation.
  2494   2565   **   -w|--ignore-all-space       Ignore white space when comparing lines
  2495   2566   **   -Z|--ignore-trailing-space  Ignore whitespace at line end
  2496   2567   **
  2497   2568   ** See also: info, finfo, timeline
  2498   2569   */
  2499   2570   void annotate_cmd(void){
  2500         -  int fnid;         /* Filename ID */
  2501         -  int fid;          /* File instance ID */
  2502         -  int mid;          /* Manifest where file was checked in */
  2503         -  int cid;          /* Checkout ID */
  2504         -  Blob treename;    /* FILENAME translated to canonical form */
  2505         -  char *zFilename;  /* Canonical filename */
  2506         -  Annotator ann;    /* The annotation of the file */
  2507         -  int i;            /* Loop counter */
  2508         -  const char *zLimit; /* The value to the -n|--limit option */
  2509         -  int iLimit;       /* How far back in time to look */
  2510         -  int showLog;      /* True to show the log */
  2511         -  int fileVers;     /* Show file version instead of check-in versions */
  2512         -  u64 annFlags = 0; /* Flags to control annotation properties */
  2513         -  int bBlame = 0;   /* True for BLAME output.  False for ANNOTATE. */
         2571  +  const char *zRevision; /* Revision name, or NULL for current check-in */
         2572  +  Annotator ann;         /* The annotation of the file */
         2573  +  int i;                 /* Loop counter */
         2574  +  const char *zLimit;    /* The value to the -n|--limit option */
         2575  +  const char *zOrig;     /* The value for -o|--origin */
         2576  +  int showLog;           /* True to show the log */
         2577  +  int fileVers;          /* Show file version instead of check-in versions */
         2578  +  u64 annFlags = 0;      /* Flags to control annotation properties */
         2579  +  int bBlame = 0;        /* True for BLAME output.  False for ANNOTATE. */
         2580  +  int szHash;            /* Display size of a version hash */
  2514   2581   
  2515   2582     bBlame = g.argv[1][0]!='a';
         2583  +  zRevision = find_option("r","revision",1);
  2516   2584     zLimit = find_option("limit","n",1);
  2517         -  if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
  2518         -  iLimit = atoi(zLimit);
         2585  +  zOrig = find_option("origin","o",1);
  2519   2586     showLog = find_option("log","l",0)!=0;
  2520   2587     if( find_option("ignore-trailing-space","Z",0)!=0 ){
  2521   2588       annFlags = DIFF_IGNORE_EOLWS;
  2522   2589     }
  2523   2590     if( find_option("ignore-all-space","w",0)!=0 ){
  2524   2591       annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
  2525   2592     }
................................................................................
  2528   2595   
  2529   2596     /* We should be done with options.. */
  2530   2597     verify_all_options();
  2531   2598   
  2532   2599     if( g.argc<3 ) {
  2533   2600       usage("FILENAME");
  2534   2601     }
  2535         -  file_tree_name(g.argv[2], &treename, 0, 1);
  2536         -  zFilename = blob_str(&treename);
  2537         -  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
  2538         -  if( fnid==0 ){
  2539         -    fossil_fatal("no such file: %s", zFilename);
  2540         -  }
  2541         -  fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename);
  2542         -  if( fid==0 ){
  2543         -    fossil_fatal("not part of current checkout: %s", zFilename);
  2544         -  }
  2545         -  cid = db_lget_int("checkout", 0);
  2546         -  if( cid == 0 ){
  2547         -    fossil_fatal("Not in a checkout");
  2548         -  }
  2549         -  if( iLimit<=0 ) iLimit = 1000000000;
  2550         -  compute_direct_ancestors(cid);
  2551         -  mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor "
  2552         -          " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid"
  2553         -          " ORDER BY ancestor.generation ASC LIMIT 1",
  2554         -          fid, fnid);
  2555         -  if( mid==0 ){
  2556         -    fossil_fatal("unable to find manifest");
  2557         -  }
  2558         -  annFlags |= (ANN_FILE_ANCEST|DIFF_STRIP_EOLCR);
  2559         -  annotate_file(&ann, fnid, mid, iLimit, annFlags);
         2602  +
         2603  +  annFlags |= DIFF_STRIP_EOLCR;
         2604  +  annotate_file(&ann, g.argv[2], zRevision, zLimit, zOrig, annFlags);
  2560   2605     if( showLog ){
  2561   2606       struct AnnVers *p;
  2562   2607       for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
  2563   2608         fossil_print("version %3d: %s %S file %S\n",
  2564   2609                      i+1, p->zDate, p->zMUuid, p->zFUuid);
  2565   2610       }
  2566   2611       fossil_print("---------------------------------------------------\n");
  2567   2612     }
         2613  +  szHash = length_of_S_display();
  2568   2614     for(i=0; i<ann.nOrig; i++){
  2569   2615       int iVers = ann.aOrig[i].iVers;
  2570   2616       char *z = (char*)ann.aOrig[i].z;
  2571   2617       int n = ann.aOrig[i].n;
  2572   2618       struct AnnVers *p;
  2573         -    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
  2574         -    p = ann.aVers + iVers;
         2619  +    if( iVers<0 && !ann.bMoreToDo ) iVers = ann.nVers-1;
  2575   2620       if( bBlame ){
  2576   2621         if( iVers>=0 ){
         2622  +        p = ann.aVers + iVers;
  2577   2623           fossil_print("%S %s %13.13s: %.*s\n",
  2578   2624                fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
  2579   2625         }else{
  2580         -        fossil_print("%35s  %.*s\n", "", n, z);
         2626  +        fossil_print("%*s %.*s\n", szHash+26, "", n, z);
  2581   2627         }
  2582   2628       }else{
  2583   2629         if( iVers>=0 ){
         2630  +        p = ann.aVers + iVers;
  2584   2631           fossil_print("%S %s %5d: %.*s\n",
  2585   2632                fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
  2586   2633         }else{
  2587         -        fossil_print("%21s %5d: %.*s\n",
  2588         -             "", i+1, n, z);
         2634  +        fossil_print("%*s %5d: %.*s\n", szHash+11, "", i+1, n, z);
  2589   2635         }
  2590   2636       }
  2591   2637     }
  2592   2638   }

Changes to src/diffcmd.c.

   261    261         blob_reset(&nameFile1);
   262    262         blob_appendf(&nameFile1, "%s~%d", zFile2, cnt++);
   263    263       }while( file_access(blob_str(&nameFile1),F_OK)==0 );
   264    264       blob_write_to_file(pFile1, blob_str(&nameFile1));
   265    265   
   266    266       /* Construct the external diff command */
   267    267       blob_zero(&cmd);
   268         -    blob_appendf(&cmd, "%s ", zDiffCmd);
          268  +    blob_append(&cmd, zDiffCmd, -1);
   269    269       if( fSwapDiff ){
   270         -      shell_escape(&cmd, zFile2);
   271         -      blob_append(&cmd, " ", 1);
   272         -      shell_escape(&cmd, blob_str(&nameFile1));
          270  +      blob_append_escaped_arg(&cmd, zFile2);
          271  +      blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
   273    272       }else{
   274         -      shell_escape(&cmd, blob_str(&nameFile1));
   275         -      blob_append(&cmd, " ", 1);
   276         -      shell_escape(&cmd, zFile2);
          273  +      blob_append_escaped_arg(&cmd, blob_str(&nameFile1));
          274  +      blob_append_escaped_arg(&cmd, zFile2);
   277    275       }
   278    276   
   279    277       /* Run the external diff command */
   280    278       fossil_system(blob_str(&cmd));
   281    279   
   282    280       /* Delete the temporary file and clean up memory used */
   283    281       file_delete(blob_str(&nameFile1));
................................................................................
   358    356       file_tempname(&temp1, blob_str(&prefix1));
   359    357       file_tempname(&temp2, blob_str(&prefix2));
   360    358       blob_write_to_file(pFile1, blob_str(&temp1));
   361    359       blob_write_to_file(pFile2, blob_str(&temp2));
   362    360   
   363    361       /* Construct the external diff command */
   364    362       blob_zero(&cmd);
   365         -    blob_appendf(&cmd, "%s ", zDiffCmd);
   366         -    shell_escape(&cmd, blob_str(&temp1));
   367         -    blob_append(&cmd, " ", 1);
   368         -    shell_escape(&cmd, blob_str(&temp2));
          363  +    blob_append(&cmd, zDiffCmd, -1);
          364  +    blob_append_escaped_arg(&cmd, blob_str(&temp1));
          365  +    blob_append_escaped_arg(&cmd, blob_str(&temp2));
   369    366   
   370    367       /* Run the external diff command */
   371    368       fossil_system(blob_str(&cmd));
   372    369   
   373    370       /* Delete the temporary file and clean up memory used */
   374    371       file_delete(blob_str(&temp1));
   375    372       file_delete(blob_str(&temp2));

Changes to src/dispatch.c.

    20     20   ** that implement those commands and web pages and their associated help
    21     21   ** text.
    22     22   */
    23     23   #include "config.h"
    24     24   #include <assert.h>
    25     25   #include "dispatch.h"
    26     26   
    27         -
    28     27   #if INTERFACE
    29     28   /*
    30     29   ** An instance of this object defines everything we need to know about an
    31         -** individual command or webpage.
           30  +** individual command, webpage, or setting.
    32     31   */
    33     32   struct CmdOrPage {
    34     33     const char *zName;       /* Name.  Webpages start with "/". Commands do not */
    35         -  void (*xFunc)(void);     /* Function that implements the command or webpage */
           34  +  void (*xFunc)(void);     /* Implementation function, or NULL for settings */
    36     35     const char *zHelp;       /* Raw help text */
    37     36     unsigned int eCmdFlags;  /* Flags */
    38     37   };
    39     38   
    40     39   /***************************************************************************
    41     40   ** These macros must match similar macros in mkindex.c
    42     41   ** Allowed values for CmdOrPage.eCmdFlags.
    43     42   */
    44         -#define CMDFLAG_1ST_TIER  0x0001      /* Most important commands */
    45         -#define CMDFLAG_2ND_TIER  0x0002      /* Obscure and seldom used commands */
    46         -#define CMDFLAG_TEST      0x0004      /* Commands for testing only */
    47         -#define CMDFLAG_WEBPAGE   0x0008      /* Web pages */
    48         -#define CMDFLAG_COMMAND   0x0010      /* A command */
           43  +#define CMDFLAG_1ST_TIER    0x0001      /* Most important commands */
           44  +#define CMDFLAG_2ND_TIER    0x0002      /* Obscure and seldom used commands */
           45  +#define CMDFLAG_TEST        0x0004      /* Commands for testing only */
           46  +#define CMDFLAG_WEBPAGE     0x0008      /* Web pages */
           47  +#define CMDFLAG_COMMAND     0x0010      /* A command */
           48  +#define CMDFLAG_SETTING     0x0020      /* A setting */
           49  +#define CMDFLAG_VERSIONABLE 0x0040      /* A versionable setting */
           50  +#define CMDFLAG_BLOCKTEXT   0x0080      /* Multi-line text setting */
           51  +#define CMDFLAG_BOOLEAN     0x0100      /* A boolean setting */
    49     52   /**************************************************************************/
    50     53   
    51     54   /* Values for the 2nd parameter to dispatch_name_search() */
    52         -#define CMDFLAG_ANY       0x0018      /* Match anything */
    53         -#define CMDFLAG_PREFIX    0x0020      /* Prefix match is ok */
           55  +#define CMDFLAG_ANY         0x0038      /* Match anything */
           56  +#define CMDFLAG_PREFIX      0x0200      /* Prefix match is ok */
    54     57   
    55     58   #endif /* INTERFACE */
    56     59   
    57     60   /*
    58     61   ** The page_index.h file contains the definition for aCommand[] - an array
    59     62   ** of CmdOrPage objects that defines all available commands and webpages
    60     63   ** known to Fossil.
................................................................................
    70     73   ** source code files looking for header comments on the functions that
    71     74   ** implement command and webpages.
    72     75   */
    73     76   #include "page_index.h"
    74     77   #define MX_COMMAND count(aCommand)
    75     78   
    76     79   /*
    77         -** Given a command or webpage name in zName, find the corresponding CmdOrPage
    78         -** object and return a pointer to that object in *ppCmd.
           80  +** Given a command, webpage, or setting name in zName, find the corresponding
           81  +** CmdOrPage object and return a pointer to that object in *ppCmd.
    79     82   **
    80         -** The eType field is CMDFLAG_COMMAND to lookup commands or CMDFLAG_WEBPAGE
    81         -** to look up webpages or CMDFLAG_ANY to look for either.  If the CMDFLAG_PREFIX
    82         -** flag is set, then a prefix match is allowed.
           83  +** The eType field is CMDFLAG_COMMAND to look up commands, CMDFLAG_WEBPAGE to
           84  +** look up webpages, CMDFLAG_SETTING to look up settings, or CMDFLAG_ANY to look
           85  +** for any.  If the CMDFLAG_PREFIX bit is set, then a prefix match is allowed.
    83     86   **
    84     87   ** Return values:
    85     88   **    0:     Success.  *ppCmd is set to the appropriate CmdOrPage
    86     89   **    1:     Not found.
    87     90   **    2:     Ambiguous.  Two or more entries match.
    88     91   */
    89     92   int dispatch_name_search(
................................................................................
   109    112         lwr = mid + 1;
   110    113       }
   111    114     }
   112    115     if( (eType & CMDFLAG_PREFIX)!=0
   113    116      && lwr<MX_COMMAND
   114    117      && strncmp(zName, aCommand[lwr].zName, nName)==0
   115    118     ){
   116         -    if( lwr<MX_COMMAND-1 && strncmp(zName, aCommand[lwr+1].zName, nName)==0 ){
   117         -      return 2;  /* Ambiguous prefix */
   118         -    }else{
   119         -      *ppCmd = &aCommand[lwr];
          119  +    /* An inexact prefix match was found.  Scan the name table to try to find
          120  +     * exactly one entry with this prefix and the requested type. */
          121  +    for( mid=-1; lwr<MX_COMMAND
          122  +              && strncmp(zName, aCommand[lwr].zName, nName)==0; ++lwr ){
          123  +      if( aCommand[lwr].eCmdFlags & eType ){
          124  +        if( mid<0 ){
          125  +          mid = lwr;  /* Potential ambiguous prefix */
          126  +        }else{
          127  +          return 2;  /* Confirmed ambiguous prefix */
          128  +        }
          129  +      }
          130  +    }
          131  +    if( mid>=0 ){
          132  +      *ppCmd = &aCommand[mid];
   120    133         return 0;  /* Prefix match */
   121    134       }
   122    135     }
   123    136     return 1;  /* Not found */
   124    137   }
          138  +
          139  +/*
          140  +** zName is the name of a webpage (eType==CMDFLAGS_WEBPAGE) that does not
          141  +** exist in the dispatch table.  Check to see if this webpage name exists
          142  +** as an alias in the CONFIG table of the repository.  If it is, then make
          143  +** appropriate changes to the CGI environment and set *ppCmd to point to the
          144  +** aliased command.
          145  +**
          146  +** Return 0 if the command is successfully aliased.  Return 1 if there
          147  +** is not alias for zName.  Any kind of error in the alias value causes a
          148  +** error to be thrown.
          149  +**
          150  +** Alias entries in the CONFIG table have a "name" value of "walias:NAME"
          151  +** where NAME is the input page name.  The value is a string of the form
          152  +** "NEWNAME?QUERYPARAMS".  The ?QUERYPARAMS is optional.  If present (and it
          153  +** usually is), then all query parameters are added to the CGI environment.
          154  +** Except, query parameters of the form "X!" cause any CGI X variable to be
          155  +** removed.
          156  +*/
          157  +int dispatch_alias(const char *zName, const CmdOrPage **ppCmd){
          158  +  char *z;
          159  +  char *zQ;
          160  +  int i;
          161  +
          162  +  z = db_text(0, "SELECT value FROM config WHERE name='walias:%q'",zName);
          163  +  if( z==0 ) return 1;
          164  +  for(i=0; z[i] && z[i]!='?'; i++){}
          165  +  if( z[i]=='?' ){
          166  +    z[i] = 0;
          167  +    zQ = &z[i+1];
          168  +  }else{
          169  +    zQ = &z[i];
          170  +  }
          171  +  if( dispatch_name_search(z, CMDFLAG_WEBPAGE, ppCmd) ){
          172  +    fossil_fatal("\"%s\" aliased to \"%s\" but \"%s\" does not exist",
          173  +                 zName, z, z);
          174  +  }
          175  +  z = zQ;
          176  +  while( *z ){
          177  +    char *zName = z;
          178  +    char *zValue = 0;
          179  +    while( *z && *z!='=' && *z!='&' && *z!='!' ){ z++; }
          180  +    if( *z=='=' ){
          181  +      *z = 0;
          182  +      z++;
          183  +      zValue = z;
          184  +      while( *z && *z!='&' ){ z++; }
          185  +      if( *z ){
          186  +        *z = 0;
          187  +        z++;
          188  +      }
          189  +      dehttpize(zValue);
          190  +    }else if( *z=='!' ){
          191  +      *(z++) = 0;
          192  +      cgi_delete_query_parameter(zName);
          193  +      zName = "";
          194  +    }else{
          195  +      if( *z ){ *z++ = 0; }
          196  +      zValue = "";
          197  +    }
          198  +    if( fossil_islower(zName[0]) ){
          199  +      cgi_replace_query_parameter(zName, zValue);
          200  +    }
          201  +  }
          202  +  return 0;
          203  +}
   125    204   
   126    205   /*
   127    206   ** Fill Blob with a space-separated list of all command names that
   128    207   ** match the prefix zPrefix.
   129    208   */
   130    209   void dispatch_matching_names(const char *zPrefix, Blob *pList){
   131    210     int i;
................................................................................
   172    251   ** Defaults to just the CLI commands.  Specify --www to see only the
   173    252   ** web pages, or --everything to see both commands and pages.
   174    253   **
   175    254   ** Options:
   176    255   **    -e|--everything   Show all commands and pages.
   177    256   **    -t|--test         Include test- commands
   178    257   **    -w|--www          Show WWW pages.
          258  +**    -s|--settings     Show settings.
   179    259   **    -h|--html         Transform output to HTML.
   180    260   */
   181    261   void test_all_help_cmd(void){
   182    262     int i;
   183    263     int mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER;
   184    264     int useHtml = find_option("html","h",0)!=0;
   185    265   
   186    266     if( find_option("www","w",0) ){
   187    267       mask = CMDFLAG_WEBPAGE;
   188    268     }
   189    269     if( find_option("everything","e",0) ){
   190    270       mask = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER | CMDFLAG_WEBPAGE;
          271  +  }
          272  +  if( find_option("settings","s",0) ){
          273  +    mask = CMDFLAG_SETTING;
   191    274     }
   192    275     if( find_option("test","t",0) ){
   193    276       mask |= CMDFLAG_TEST;
   194    277     }
   195    278     if( useHtml ) fossil_print("<!--\n");
   196    279     fossil_print("Help text for:\n");
   197    280     if( mask & CMDFLAG_1ST_TIER ) fossil_print(" * Commands\n");
   198    281     if( mask & CMDFLAG_2ND_TIER ) fossil_print(" * Auxiliary commands\n");
   199    282     if( mask & CMDFLAG_TEST )     fossil_print(" * Test commands\n");
   200    283     if( mask & CMDFLAG_WEBPAGE )  fossil_print(" * Web pages\n");
          284  +  if( mask & CMDFLAG_SETTING )  fossil_print(" * Settings\n");
   201    285     if( useHtml ){
   202    286       fossil_print("-->\n");
   203    287       fossil_print("<!-- start_all_help -->\n");
   204    288     }else{
   205    289       fossil_print("---\n");
   206    290     }
   207    291     for(i=0; i<MX_COMMAND; i++){
................................................................................
   226    310   }
   227    311   
   228    312   /*
   229    313   ** WEBPAGE: help
   230    314   ** URL: /help?name=CMD
   231    315   **
   232    316   ** Show the built-in help text for CMD.  CMD can be a command-line interface
   233         -** command or a page name from the web interface.
          317  +** command or a page name from the web interface or a setting.
   234    318   */
   235    319   void help_page(void){
   236    320     const char *zCmd = P("cmd");
   237    321   
   238    322     if( zCmd==0 ) zCmd = P("name");
   239    323     if( zCmd && *zCmd ){
   240    324       int rc;
   241    325       const CmdOrPage *pCmd = 0;
   242    326   
   243    327       style_header("Help: %s", zCmd);
   244    328   
   245    329       style_submenu_element("Command-List", "%s/help", g.zTop);
          330  +    rc = dispatch_name_search(zCmd, CMDFLAG_ANY, &pCmd);
   246    331       if( *zCmd=='/' ){
   247    332         /* Some of the webpages require query parameters in order to work.
   248    333         ** @ <h1>The "<a href='%R%s(zCmd)'>%s(zCmd)</a>" page:</h1> */
   249    334         @ <h1>The "%h(zCmd)" page:</h1>
          335  +    }else if( rc==0 && (pCmd->eCmdFlags & CMDFLAG_SETTING)!=0 ){
          336  +      @ <h1>The "%h(pCmd->zName)" setting:</h1>
   250    337       }else{
   251    338         @ <h1>The "%h(zCmd)" command:</h1>
   252    339       }
   253         -    rc = dispatch_name_search(zCmd, CMDFLAG_ANY, &pCmd);
   254    340       if( rc==1 ){
   255    341         @ unknown command: %h(zCmd)
   256    342       }else if( rc==2 ){
   257    343         @ ambiguous command prefix: %h(zCmd)
   258    344       }else{
   259    345         if( pCmd->zHelp[0]==0 ){
   260         -        @ no help available for the %h(pCmd->zName) command
          346  +        @ No help available for "%h(pCmd->zName)"
   261    347         }else{
   262    348           @ <blockquote>
   263    349           help_to_html(pCmd->zHelp, cgi_output_blob());
   264    350           @ </blockquote>
   265    351         }
   266    352       }
   267    353     }else{
................................................................................
   336    422       }
   337    423       n = (j+3)/4;
   338    424       for(i=j=0; i<MX_COMMAND; i++){
   339    425         const char *z = aCommand[i].zName;
   340    426         if( strncmp(z,"test",4)!=0 ) continue;
   341    427         if( j==0 ){
   342    428           @ <td valign="top"><ul>
          429  +      }
          430  +      if( aCommand[i].zHelp[0] ){
          431  +        @ <li><a href="%R/help?cmd=%s(z)">%s(z)</a></li>
          432  +      }else{
          433  +        @ <li>%s(z)</li>
          434  +      }
          435  +      j++;
          436  +      if( j>=n ){
          437  +        @ </ul></td>
          438  +        j = 0;
          439  +      }
          440  +    }
          441  +    if( j>0 ){
          442  +      @ </ul></td>
          443  +    }
          444  +    @ </tr></table>
          445  +
          446  +    @ <h1>Settings:</h1>
          447  +    @ <table border="0"><tr>
          448  +    for(i=j=0; i<MX_COMMAND; i++){
          449  +      if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
          450  +      j++;
          451  +    }
          452  +    n = (j+4)/5;
          453  +    for(i=j=0; i<MX_COMMAND; i++){
          454  +      const char *z = aCommand[i].zName;
          455  +      if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)==0 ) continue;
          456  +      if( j==0 ){
          457  +        @ <td valign="top"><ul>
   343    458         }
   344    459         if( aCommand[i].zHelp[0] ){
   345    460           @ <li><a href="%R/help?cmd=%s(z)">%s(z)</a></li>
   346    461         }else{
   347    462           @ <li>%s(z)</li>
   348    463         }
   349    464         j++;
................................................................................
   434    549     }
   435    550     multi_column_list(aCmd, nCmd);
   436    551   }
   437    552   
   438    553   /*
   439    554   ** COMMAND: help
   440    555   **
   441         -** Usage: %fossil help COMMAND
   442         -**    or: %fossil COMMAND --help
          556  +** Usage: %fossil help TOPIC
          557  +**    or: %fossil TOPIC --help
   443    558   **
   444         -** Display information on how to use COMMAND.  To display a list of
   445         -** available commands use one of:
          559  +** Display information on how to use TOPIC, which may be a command, webpage, or
          560  +** setting.  Webpage names begin with "/".  To display a list of available
          561  +** topics, use one of:
   446    562   **
   447         -**    %fossil help              Show common commands
   448         -**    %fossil help -a|--all     Show both common and auxiliary commands
   449         -**    %fossil help -t|--test    Show test commands only
   450         -**    %fossil help -x|--aux     Show auxiliary commands only
   451         -**    %fossil help -w|--www     Show list of WWW pages
          563  +**    %fossil help                Show common commands
          564  +**    %fossil help -a|--all       Show both common and auxiliary commands
          565  +**    %fossil help -s|--settings  Show setting names
          566  +**    %fossil help -t|--test      Show test commands only
          567  +**    %fossil help -x|--aux       Show auxiliary commands only
          568  +**    %fossil help -w|--www       Show list of webpages
   452    569   */
   453    570   void help_cmd(void){
   454    571     int rc;
   455    572     int isPage = 0;
   456    573     const char *z;
   457    574     const char *zCmdOrPage;
   458    575     const char *zCmdOrPagePlural;
   459    576     const CmdOrPage *pCmd = 0;
   460    577     if( g.argc<3 ){
   461    578       z = g.argv[0];
   462    579       fossil_print(
   463         -      "Usage: %s help COMMAND\n"
   464         -      "Common COMMANDs:  (use \"%s help -a|--all\" for a complete list)\n",
          580  +      "Usage: %s help TOPIC\n"
          581  +      "Common commands:  (use \"%s help -a|--all\" for a complete list)\n",
   465    582         z, z);
   466    583       command_list(0, CMDFLAG_1ST_TIER);
   467    584       version_cmd();
   468    585       return;
   469    586     }
   470    587     if( find_option("all","a",0) ){
   471    588       command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
................................................................................
   478    595     else if( find_option("aux","x",0) ){
   479    596       command_list(0, CMDFLAG_2ND_TIER);
   480    597       return;
   481    598     }
   482    599     else if( find_option("test","t",0) ){
   483    600       command_list(0, CMDFLAG_TEST);
   484    601       return;
          602  +  }
          603  +  else if( find_option("setting","s",0) ){
          604  +    command_list(0, CMDFLAG_SETTING);
          605  +    return;
   485    606     }
   486    607     isPage = ('/' == *g.argv[2]) ? 1 : 0;
   487    608     if(isPage){
   488    609       zCmdOrPage = "page";
   489    610       zCmdOrPagePlural = "pages";
   490    611     }else{
   491         -    zCmdOrPage = "command";
   492         -    zCmdOrPagePlural = "commands";
          612  +    zCmdOrPage = "command or setting";
          613  +    zCmdOrPagePlural = "commands and settings";
   493    614     }
   494    615     rc = dispatch_name_search(g.argv[2], CMDFLAG_ANY|CMDFLAG_PREFIX, &pCmd);
   495    616     if( rc==1 ){
   496         -    fossil_print("unknown %s: %s\nAvailable %s:\n",
   497         -                 zCmdOrPage, g.argv[2], zCmdOrPagePlural);
   498         -    command_list(0, isPage ? CMDFLAG_WEBPAGE : (0xff & ~CMDFLAG_WEBPAGE));
          617  +    fossil_print("unknown %s: %s\nConsider using:\n", zCmdOrPage, g.argv[2]);
          618  +    fossil_print("   fossil help -a     ;# show all commands\n");
          619  +    fossil_print("   fossil help -w     ;# show all web-pages\n");
          620  +    fossil_print("   fossil help -s     ;# show all settings\n");
   499    621       fossil_exit(1);
   500    622     }else if( rc==2 ){
   501    623       fossil_print("ambiguous %s prefix: %s\nMatching %s:\n",
   502    624                    zCmdOrPage, g.argv[2], zCmdOrPagePlural);
   503    625       command_list(g.argv[2], 0xff);
   504    626       fossil_exit(1);
   505    627     }
   506    628     z = pCmd->zHelp;
   507    629     if( z==0 ){
   508    630       fossil_fatal("no help available for the %s %s",
   509    631                    pCmd->zName, zCmdOrPage);
          632  +  }
          633  +  if( pCmd->eCmdFlags & CMDFLAG_SETTING ){
          634  +    fossil_print("Setting: \"%s\"%s\n\n",
          635  +         pCmd->zName,
          636  +         (pCmd->eCmdFlags & CMDFLAG_VERSIONABLE)!=0 ? " (versionable)" : ""
          637  +    );
   510    638     }
   511    639     while( *z ){
   512    640       if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
   513    641         fossil_print("%s", g.argv[0]);
   514    642         z += 7;
   515    643       }else{
   516    644         putchar(*z);
   517    645         z++;
   518    646       }
   519    647     }
   520    648     putchar('\n');
   521    649   }
          650  +
          651  +/*
          652  +** Return a pointer to the setting information array.
          653  +**
          654  +** This routine provides access to the aSetting2[] array which is created
          655  +** by the mkindex utility program and included with <page_index.h>.
          656  +*/
          657  +const Setting *setting_info(int *pnCount){
          658  +  if( pnCount ) *pnCount = (int)(sizeof(aSetting)/sizeof(aSetting[0]));
          659  +  return aSetting;
          660  +}

Changes to src/doc.c.

   462    462   
   463    463   /*
   464    464   ** Look for a file named zName in the check-in with RID=vid.  Load the content
   465    465   ** of that file into pContent and return the RID for the file.  Or return 0
   466    466   ** if the file is not found or could not be loaded.
   467    467   */
   468    468   int doc_load_content(int vid, const char *zName, Blob *pContent){
          469  +  int writable = db_is_writeable("repository");
   469    470     int rid;   /* The RID of the file being loaded */
   470         -  if( !db_table_exists("repository","vcache") ){
          471  +  if( !db_table_exists("repository", "vcache") || !writable ){
   471    472       db_multi_exec(
   472         -      "CREATE TABLE IF NOT EXISTS vcache(\n"
          473  +      "CREATE %s TABLE IF NOT EXISTS vcache(\n"
   473    474         "  vid INTEGER,         -- check-in ID\n"
   474    475         "  fname TEXT,          -- filename\n"
   475    476         "  rid INTEGER,         -- artifact ID\n"
   476    477         "  PRIMARY KEY(vid,fname)\n"
   477         -      ") WITHOUT ROWID"
          478  +      ") WITHOUT ROWID", writable ? "" : "TEMPORARY"
   478    479       );
   479    480     }
   480    481     if( !db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
   481    482       db_multi_exec(
   482    483         "DELETE FROM vcache;\n"
   483    484         "CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;\n"
   484    485         "INSERT INTO vcache(vid,fname,rid)"
................................................................................
   494    495       rid = 0;
   495    496     }
   496    497     return rid;
   497    498   }
   498    499   
   499    500   /*
   500    501   ** Transfer content to the output.  During the transfer, when text of
   501         -** the followign form is seen:
          502  +** the following form is seen:
   502    503   **
   503    504   **       href="$ROOT/
   504    505   **       action="$ROOT/
   505    506   **
   506    507   ** Convert $ROOT to the root URI of the repository.  Allow ' in place of "
   507         -** and any case for href.
          508  +** and any case for href or action.
   508    509   */
   509    510   static void convert_href_and_output(Blob *pIn){
   510    511     int i, base;
   511    512     int n = blob_size(pIn);
   512    513     char *z = blob_buffer(pIn);
   513    514     for(base=0, i=7; i<n; i++){
   514    515       if( z[i]=='$'

Changes to src/event.c.

   330    330     nrid = content_put(&event);
   331    331     db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
   332    332     if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
   333    333       db_end_transaction(1);
   334    334       return 0;
   335    335     }
   336    336     assert( blob_is_reset(&event) );
   337         -  content_deltify(rid, nrid, 0);
          337  +  content_deltify(rid, &nrid, 1, 0);
   338    338     db_end_transaction(0);
   339    339     return 1;
   340    340   }
   341    341   
   342    342   /*
   343    343   ** WEBPAGE: technoteedit
   344    344   ** WEBPAGE: eventedit

Changes to src/file.c.

    86     86   ** Fill stat buf with information received from stat() or lstat().
    87     87   ** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on.
    88     88   **
    89     89   */
    90     90   static int fossil_stat(
    91     91     const char *zFilename,  /* name of file or directory to inspect. */
    92     92     struct fossilStat *buf, /* pointer to buffer where info should go. */
    93         -  int isWd,               /* non-zero to consider look at symlink itself. */
    94         -  int forceWd             /* non-zero to force look at symlink itself. */
           93  +  int isWd                /* non-zero to consider look at symlink itself. */
    95     94   ){
    96     95     int rc;
    97     96     void *zMbcs = fossil_utf8_to_path(zFilename, 0);
    98     97   #if !defined(_WIN32)
    99         -  if( isWd && (forceWd || db_allow_symlinks(0)) ){
           98  +  if( isWd && db_allow_symlinks() ){
   100     99       rc = lstat(zMbcs, buf);
   101    100     }else{
   102    101       rc = stat(zMbcs, buf);
   103    102     }
   104    103   #else
   105    104     rc = win32_stat(zMbcs, buf, isWd);
   106    105   #endif
................................................................................
   126    125   ** Return the number of errors.  No error messages are generated.
   127    126   */
   128    127   static int getStat(const char *zFilename, int isWd){
   129    128     int rc = 0;
   130    129     if( zFilename==0 ){
   131    130       if( fileStatValid==0 ) rc = 1;
   132    131     }else{
   133         -    if( fossil_stat(zFilename, &fileStat, isWd, 0)!=0 ){
          132  +    if( fossil_stat(zFilename, &fileStat, isWd)!=0 ){
   134    133         fileStatValid = 0;
   135    134         rc = 1;
   136    135       }else{
   137    136         fileStatValid = 1;
   138    137         rc = 0;
   139    138       }
   140    139     }
................................................................................
   218    217   ** Create symlink to file on Unix, or plain-text file with
   219    218   ** symlink target if "allow-symlinks" is off or we're on Windows.
   220    219   **
   221    220   ** Arguments: target file (symlink will point to it), link file
   222    221   **/
   223    222   void symlink_create(const char *zTargetFile, const char *zLinkFile){
   224    223   #if !defined(_WIN32)
   225         -  if( db_allow_symlinks(0) ){
          224  +  if( db_allow_symlinks() ){
   226    225       int i, nName;
   227    226       char *zName, zBuf[1000];
   228    227   
   229    228       nName = strlen(zLinkFile);
   230    229       if( nName>=sizeof(zBuf) ){
   231    230         zName = mprintf("%s", zLinkFile);
   232    231       }else{
................................................................................
   275    274   **   - PERM_REG for all other cases (regular file, directory, fifo, etc).
   276    275   */
   277    276   int file_wd_perm(const char *zFilename){
   278    277   #if !defined(_WIN32)
   279    278     if( !getStat(zFilename, 1) ){
   280    279        if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
   281    280         return PERM_EXE;
   282         -    else if( db_allow_symlinks(0) && S_ISLNK(fileStat.st_mode) )
          281  +    else if( db_allow_symlinks() && S_ISLNK(fileStat.st_mode) )
   283    282         return PERM_LNK;
   284    283     }
   285    284   #endif
   286    285     return PERM_REG;
   287    286   }
   288    287   
   289    288   /*
................................................................................
   328    327   ** zFilename is a directory -OR- a symlink that points to a directory.
   329    328   ** Return 0 if zFilename does not exist.  Return 2 if zFilename exists
   330    329   ** but is something other than a directory.
   331    330   */
   332    331   int file_wd_isdir(const char *zFilename){
   333    332     int rc;
   334    333     char *zFN;
   335         -  struct fossilStat dirFileStat;
   336    334   
   337    335     zFN = mprintf("%s", zFilename);
   338    336     file_simplify_name(zFN, -1, 0);
   339         -  memset(&dirFileStat, 0, sizeof(struct fossilStat));
   340         -  rc = fossil_stat(zFN, &dirFileStat, 1, 1);
          337  +  rc = getStat(zFN, 1);
   341    338     if( rc ){
   342    339       rc = 0; /* It does not exist at all. */
   343         -  }else if( S_ISDIR(dirFileStat.st_mode) ){
          340  +  }else if( S_ISDIR(fileStat.st_mode) ){
   344    341       rc = 1; /* It exists and is a real directory. */
   345         -  }else if( !db_allow_symlinks(1) && S_ISLNK(dirFileStat.st_mode) ){
          342  +  }else if( S_ISLNK(fileStat.st_mode) ){
   346    343       Blob content;
   347    344       blob_read_link(&content, zFN); /* It exists and is a link. */
   348    345       rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */
   349    346       blob_reset(&content);
   350    347     }else{
   351    348       rc = 2; /* It exists and is something else. */
   352    349     }
................................................................................
   509    506   ** Set or clear the execute bit on a file.  Return true if a change
   510    507   ** occurred and false if this routine is a no-op.
   511    508   */
   512    509   int file_wd_setexe(const char *zFilename, int onoff){
   513    510     int rc = 0;
   514    511   #if !defined(_WIN32)
   515    512     struct stat buf;
   516         -  if( fossil_stat(zFilename, &buf, 1, 0)!=0 || S_ISLNK(buf.st_mode) ) return 0;
          513  +  if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
   517    514     if( onoff ){
   518    515       int targetMode = (buf.st_mode & 0444)>>2;
   519    516       if( (buf.st_mode & 0100)==0 ){
   520    517         chmod(zFilename, buf.st_mode | targetMode);
   521    518         rc = 1;
   522    519       }
   523    520     }else{
................................................................................
   624    621   ** Create the tree of directories in which zFilename belongs, if that sequence
   625    622   ** of directories does not already exist.
   626    623   **
   627    624   ** On success, return zero.  On error, return errorReturn if positive, otherwise
   628    625   ** print an error message and abort.
   629    626   */
   630    627   int file_mkfolder(const char *zFilename, int forceFlag, int errorReturn){
   631         -  int i, nName, rc = 0;
          628  +  int nName, rc = 0;
   632    629     char *zName;
   633    630   
   634    631     nName = strlen(zFilename);
   635    632     zName = mprintf("%s", zFilename);
   636    633     nName = file_simplify_name(zName, nName, 0);
   637         -  for(i=1; i<nName; i++){
   638         -    if( zName[i]=='/' ){
   639         -      zName[i] = 0;
   640         -#if defined(_WIN32) || defined(__CYGWIN__)
   641         -      /*
   642         -      ** On Windows, local path looks like: C:/develop/project/file.txt
   643         -      ** The if stops us from trying to create a directory of a drive letter
   644         -      ** C: in this example.
   645         -      */
   646         -      if( !(i==2 && zName[1]==':') ){
   647         -#endif
          634  +  while( nName>0 && zName[nName-1]!='/' ){ nName--; }
          635  +  if( nName ){
          636  +    zName[nName-1] = 0;
          637  +    if( file_wd_isdir(zName)!=1 ){
          638  +      rc = file_mkfolder(zName, forceFlag, errorReturn);
          639  +      if( rc==0 ){
   648    640           if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){
   649         -          if (errorReturn <= 0) {
          641  +          if( errorReturn <= 0 ){
   650    642               fossil_fatal_recursive("unable to create directory %s", zName);
   651    643             }
   652    644             rc = errorReturn;
   653         -          break;
   654    645           }
   655         -#if defined(_WIN32) || defined(__CYGWIN__)
   656    646         }
   657         -#endif
   658         -      zName[i] = '/';
   659    647       }
   660    648     }
   661    649     free(zName);
   662    650     return rc;
   663    651   }
   664    652   
   665    653   /*
................................................................................
   985    973     file_canonical_name(zPath, &x, slash);
   986    974     fossil_print("%s[%s] -> [%s]\n", raw ? "RAW " : "", zPath, blob_buffer(&x));
   987    975     blob_reset(&x);
   988    976     if( raw ){
   989    977       int rc;
   990    978       struct fossilStat testFileStat;
   991    979       memset(&testFileStat, 0, sizeof(struct fossilStat));
   992         -    rc = fossil_stat(zPath, &testFileStat, 0, 0);
          980  +    rc = fossil_stat(zPath, &testFileStat, 0);
   993    981       fossil_print("  stat_rc      = %d\n", rc);
   994    982       sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_size);
   995    983       fossil_print("  stat_size    = %s\n", zBuf);
   996    984       sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_mtime);
   997    985       fossil_print("  stat_mtime   = %s\n", zBuf);
   998    986       fossil_print("  stat_mode    = %d\n", testFileStat.st_mode);
   999    987       memset(&testFileStat, 0, sizeof(struct fossilStat));
  1000         -    rc = fossil_stat(zPath, &testFileStat, 1, 1);
          988  +    rc = fossil_stat(zPath, &testFileStat, 1);
  1001    989       fossil_print("  l_stat_rc    = %d\n", rc);
  1002    990       sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_size);
  1003    991       fossil_print("  l_stat_size  = %s\n", zBuf);
  1004    992       sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", testFileStat.st_mtime);
  1005    993       fossil_print("  l_stat_mtime = %s\n", zBuf);
  1006    994       fossil_print("  l_stat_mode  = %d\n", testFileStat.st_mode);
  1007    995     }else{
................................................................................
  1029   1017   ** display file system information about the files specified, if any.
  1030   1018   **
  1031   1019   ** Options:
  1032   1020   **
  1033   1021   **     --open-config        Open the configuration database first.
  1034   1022   **     --slash              Trailing slashes, if any, are retained.
  1035   1023   **     --reset              Reset cached stat() info for each file.
  1036         -**     --symlinks BOOLEAN   Force allow-symlinks on or off
  1037   1024   */
  1038   1025   void cmd_test_file_environment(void){
  1039   1026     int i;
  1040   1027     int slashFlag = find_option("slash",0,0)!=0;
  1041   1028     int resetFlag = find_option("reset",0,0)!=0;
  1042         -  const char *forceSymlinks = find_option("symlinks",0,1);
  1043   1029     if( find_option("open-config", 0, 0)!=0 ){
  1044   1030       Th_OpenConfig(1);
  1045   1031     }
  1046         -  if( forceSymlinks ){
  1047         -    if( is_truth(forceSymlinks) ) g.allowSymlinks = 1;
  1048         -    if( is_false(forceSymlinks) ) g.allowSymlinks = 0;
  1049         -  }
  1050         -  fossil_print("Th_IsLocalOpen() = %d\n", Th_IsLocalOpen());
  1051         -  fossil_print("Th_IsRepositoryOpen() = %d\n", Th_IsRepositoryOpen());
  1052         -  fossil_print("Th_IsConfigOpen() = %d\n", Th_IsConfigOpen());
  1053   1032     fossil_print("filenames_are_case_sensitive() = %d\n",
  1054   1033                  filenames_are_case_sensitive());
  1055   1034     fossil_print("db_allow_symlinks_by_default() = %d\n",
  1056   1035                  db_allow_symlinks_by_default());
  1057         -  fossil_print("db_allow_symlinks(0) = %d\n", db_allow_symlinks(0));
  1058         -  fossil_print("db_allow_symlinks(1) = %d\n", db_allow_symlinks(1));
         1036  +  fossil_print("db_allow_symlinks() = %d\n", db_allow_symlinks());
  1059   1037     for(i=2; i<g.argc; i++){
  1060   1038       emitFileStat(g.argv[i], 1, slashFlag, resetFlag);
  1061   1039       emitFileStat(g.argv[i], 0, slashFlag, resetFlag);
  1062   1040     }
  1063   1041   }
  1064   1042   
  1065   1043   /*
  1066   1044   ** COMMAND: test-canonical-name
  1067   1045   **
  1068   1046   ** Usage: %fossil test-canonical-name FILENAME...
  1069   1047   **
  1070   1048   ** Test the operation of the canonical name generator.
  1071   1049   ** Also test Fossil's ability to measure attributes of a file.
  1072         -**
  1073         -** Options:
  1074         -**
  1075         -**     --open-config        Open the configuration database first.
  1076         -**     --slash              Trailing slashes, if any, are retained.
  1077         -**     --reset              Reset cached stat() info for each file.
  1078   1050   */
  1079   1051   void cmd_test_canonical_name(void){
  1080   1052     int i;
         1053  +  Blob x;
  1081   1054     int slashFlag = find_option("slash",0,0)!=0;
  1082         -  int resetFlag = find_option("reset",0,0)!=0;
  1083         -  if( find_option("open-config", 0, 0)!=0 ){
  1084         -    Th_OpenConfig(1);
  1085         -  }
         1055  +  blob_zero(&x);
  1086   1056     for(i=2; i<g.argc; i++){
  1087         -    emitFileStat(g.argv[i], 0, slashFlag, resetFlag);
         1057  +    char zBuf[100];
         1058  +    const char *zName = g.argv[i];
         1059  +    file_canonical_name(zName, &x, slashFlag);
         1060  +    fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
         1061  +    blob_reset(&x);
         1062  +    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
         1063  +    fossil_print("  file_size   = %s\n", zBuf);
         1064  +    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
         1065  +    fossil_print("  file_mtime  = %s\n", zBuf);
         1066  +    fossil_print("  file_isfile = %d\n", file_wd_isfile(zName));
         1067  +    fossil_print("  file_isfile_or_link = %d\n",file_wd_isfile_or_link(zName));
         1068  +    fossil_print("  file_islink = %d\n", file_wd_islink(zName));
         1069  +    fossil_print("  file_isexe  = %d\n", file_wd_isexe(zName));
         1070  +    fossil_print("  file_isdir  = %d\n", file_wd_isdir(zName));
  1088   1071     }
  1089   1072   }
  1090   1073   
  1091   1074   /*
  1092   1075   ** Return TRUE if the given filename is canonical.
  1093   1076   **
  1094   1077   ** Canonical names are full pathnames using "/" not "\" and which
................................................................................
  1195   1178     }
  1196   1179   }
  1197   1180   
  1198   1181   /*
  1199   1182   ** COMMAND: test-relative-name
  1200   1183   **
  1201   1184   ** Test the operation of the relative name generator.
  1202         -**
  1203         -** Options:
  1204         -**
  1205         -**     --slash              Trailing slashes, if any, are retained.
  1206   1185   */
  1207   1186   void cmd_test_relative_name(void){
  1208   1187     int i;
  1209   1188     Blob x;
  1210   1189     int slashFlag = find_option("slash",0,0)!=0;
  1211   1190     blob_zero(&x);
  1212   1191     for(i=2; i<g.argc; i++){
................................................................................
  1318   1297   **
  1319   1298   ** Test the operation of the tree name generator.
  1320   1299   **
  1321   1300   ** Options:
  1322   1301   **   --absolute           Return an absolute path instead of a relative one.
  1323   1302   **   --case-sensitive B   Enable or disable case-sensitive filenames.  B is
  1324   1303   **                        a boolean: "yes", "no", "true", "false", etc.
  1325         -**   --no-dir-symlinks    Disables support for directory symlinks.
  1326   1304   */
  1327   1305   void cmd_test_tree_name(void){
  1328   1306     int i;
  1329   1307     Blob x;
  1330   1308     int absoluteFlag = find_option("absolute",0,0)!=0;
  1331   1309     db_find_and_open_repository(0,0);
  1332   1310     blob_zero(&x);
................................................................................
  1386   1364   #if defined(_WIN32)
  1387   1365     const char *azDirs[] = {
  1388   1366        0, /* GetTempPath */
  1389   1367        0, /* TEMP */
  1390   1368        0, /* TMP */
  1391   1369        ".",
  1392   1370     };
         1371  +  char *z;
  1393   1372   #else
  1394   1373     static const char *azDirs[] = {
  1395   1374        0, /* TMPDIR */
  1396   1375        "/var/tmp",
  1397   1376        "/usr/tmp",
  1398   1377        "/tmp",
  1399   1378        "/temp",
................................................................................
  1410   1389     char zRand[16];
  1411   1390   
  1412   1391   #if defined(_WIN32)
  1413   1392     wchar_t zTmpPath[MAX_PATH];
  1414   1393   
  1415   1394     if( GetTempPathW(MAX_PATH, zTmpPath) ){
  1416   1395       azDirs[0] = fossil_path_to_utf8(zTmpPath);
         1396  +    /* Removing trailing \ from the temp path */
         1397  +    z = (char*)azDirs[0];
         1398  +    i = (int)strlen(z)-1;
         1399  +    if( i>0 && z[i]=='\\' ) z[i] = 0;
  1417   1400     }
  1418   1401   
  1419   1402     azDirs[1] = fossil_getenv("TEMP");
  1420   1403     azDirs[2] = fossil_getenv("TMP");
  1421   1404   #else
  1422   1405     azDirs[0] = fossil_getenv("TMPDIR");
  1423   1406   #endif
................................................................................
  1440   1423       blob_appendf(pBuf, "%s/%s-%s.txt", zDir, zPrefix ? zPrefix : "", zRand);
  1441   1424     }while( file_size(blob_str(pBuf))>=0 );
  1442   1425   
  1443   1426   #if defined(_WIN32)
  1444   1427     fossil_path_free((char *)azDirs[0]);
  1445   1428     fossil_path_free((char *)azDirs[1]);
  1446   1429     fossil_path_free((char *)azDirs[2]);
         1430  +  /* Change all \ characters in the windows path into / so that they can
         1431  +  ** be safely passed to a subcommand, such as by gdiff */
         1432  +  z = blob_buffer(pBuf);
         1433  +  for(i=0; z[i]; i++) if( z[i]=='\\' ) z[i] = '/';
  1447   1434   #else
  1448   1435     fossil_path_free((char *)azDirs[0]);
  1449   1436   #endif
  1450   1437   }
  1451   1438   
         1439  +
         1440  +/*
         1441  +** COMMAND: test-tempname
         1442  +** Usage:  fossil test-name BASENAME ...
         1443  +**
         1444  +** Generate temporary filenames derived from BASENAME
         1445  +*/
         1446  +void file_test_tempname(void){
         1447  +  int i;
         1448  +  Blob x = BLOB_INITIALIZER;
         1449  +  for(i=2; i<g.argc; i++){
         1450  +    file_tempname(&x, g.argv[i]);
         1451  +    fossil_print("%s\n", blob_str(&x));
         1452  +    blob_reset(&x);
         1453  +  }
         1454  +}
         1455  +
  1452   1456   
  1453   1457   /*
  1454   1458   ** Return true if a file named zName exists and has identical content
  1455   1459   ** to the blob pContent.  If zName does not exist or if the content is
  1456   1460   ** different in any way, then return false.
  1457   1461   */
  1458   1462   int file_is_the_same(Blob *pContent, const char *zName){

Changes to src/finfo.c.

    43     43   ** Options:
    44     44   **   -b|--brief           display a brief (one line / revision) summary
    45     45   **   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
    46     46   **                        boolean: "yes", "no", "true", "false", etc.
    47     47   **   -l|--log             select log mode (the default)
    48     48   **   -n|--limit N         Display the first N changes (default unlimited).
    49     49   **                        N<=0 means no limit.
    50         -**   --no-dir-symlinks    Disables support for directory symlinks.
    51     50   **   --offset P           skip P changes
    52     51   **   -p|--print           select print mode
    53     52   **   -r|--revision R      print the given revision (or ckout, if none is given)
    54     53   **                        to stdout (only in print mode)
    55     54   **   -s|--status          select status mode (print a status indicator for FILE)
    56     55   **   -W|--width <num>     Width of lines (default is to auto-detect). Must be
    57     56   **                        >22 or 0 (= no limit, resulting in a single line per
................................................................................
   283    282   **
   284    283   **    a=DATETIME Only show changes after DATETIME
   285    284   **    b=DATETIME Only show changes before DATETIME
   286    285   **    n=NUM      Show the first NUM changes only
   287    286   **    brbg       Background color by branch name
   288    287   **    ubg        Background color by user name
   289    288   **    ci=UUID    Ancestors of a particular check-in
          289  +**    orig=UUID  If both ci and orig are supplied, only show those
          290  +**                 changes on a direct path from orig to ci.
   290    291   **    showid     Show RID values for debugging
   291    292   **
   292    293   ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
   293    294   ** year-month-day form, it may be truncated, and it may also name a
   294    295   ** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
   295    296   ** (eastward). Either no timezone suffix or "Z" means UTC.
   296    297   */
................................................................................
   298    299     Stmt q;
   299    300     const char *zFilename;
   300    301     char zPrevDate[20];
   301    302     const char *zA;
   302    303     const char *zB;
   303    304     int n;
   304    305     int baseCheckin;
          306  +  int origCheckin = 0;
   305    307     int fnid;
   306    308     Blob title;
   307    309     Blob sql;
   308    310     HQuery url;
   309    311     GraphContext *pGraph;
   310    312     int brBg = P("brbg")!=0;
   311    313     int uBg = P("ubg")!=0;
................................................................................
   330    332       style_footer();
   331    333       return;
   332    334     }
   333    335     if( g.perm.Admin ){
   334    336       style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);
   335    337     }
   336    338     if( baseCheckin ){
   337         -    compute_direct_ancestors(baseCheckin);
          339  +    if( P("orig")!=0 ){
          340  +      origCheckin = name_to_typed_rid(P("orig"),"ci");
          341  +      path_shortest_stored_in_ancestor_table(origCheckin, baseCheckin);
          342  +    }else{
          343  +      compute_direct_ancestors(baseCheckin);
          344  +    }
   338    345     }
   339    346     url_add_parameter(&url, "name", zFilename);
   340    347     blob_zero(&sql);
   341    348     blob_append_sql(&sql,
   342    349       "SELECT"
   343    350       " datetime(min(event.mtime),toLocal()),"         /* Date of change */
   344    351       " coalesce(event.ecomment, event.comment),"      /* Check-in comment */
   345    352       " coalesce(event.euser, event.user),"            /* User who made chng */
   346    353       " mlink.pid,"                                    /* Parent file rid */
   347    354       " mlink.fid,"                                    /* File rid */
   348    355       " (SELECT uuid FROM blob WHERE rid=mlink.pid),"  /* Parent file uuid */
   349         -    " (SELECT uuid FROM blob WHERE rid=mlink.fid),"  /* Current file uuid */
          356  +    " blob.uuid,"                                    /* Current file uuid */
   350    357       " (SELECT uuid FROM blob WHERE rid=mlink.mid),"  /* Check-in uuid */
   351    358       " event.bgcolor,"                                /* Background color */
   352    359       " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
   353    360                                   " AND tagxref.rid=mlink.mid)," /* Branchname */
   354    361       " mlink.mid,"                                    /* check-in ID */
   355         -    " mlink.pfnid"                                   /* Previous filename */
   356         -    "  FROM mlink, event"
          362  +    " mlink.pfnid,"                                  /* Previous filename */
          363  +    " blob.size"                                     /* File size */
          364  +    "  FROM mlink, event, blob"
   357    365       " WHERE mlink.fnid=%d"
   358         -    "   AND event.objid=mlink.mid",
          366  +    "   AND event.objid=mlink.mid"
          367  +    "   AND mlink.fid=blob.rid",
   359    368       TAG_BRANCH, fnid
   360    369     );
   361    370     if( (zA = P("a"))!=0 ){
   362    371       blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zA);
   363    372       url_add_parameter(&url, "a", zA);
   364    373     }
   365    374     if( (zB = P("b"))!=0 ){
................................................................................
   395    404       @ <p>SQL: %h(blob_str(&sql))</p>
   396    405     }
   397    406     blob_reset(&sql);
   398    407     blob_zero(&title);
   399    408     if( baseCheckin ){
   400    409       char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
   401    410       char *zLink = href("%R/info/%!S", zUuid);
   402         -    if( n>0 ){
          411  +    if( origCheckin ){
          412  +      blob_appendf(&title, "Changes to file ");
          413  +    }else if( n>0 ){
   403    414         blob_appendf(&title, "First %d ancestors of file ", n);
   404    415       }else{
   405    416         blob_appendf(&title, "Ancestors of file ");
   406    417       }
   407    418       blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>",
   408    419                    zFilename, zFilename);
   409    420       if( fShowId ) blob_appendf(&title, " (%d)", fnid);
   410         -    blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
          421  +    blob_append(&title, origCheckin ? " between " : " from ", -1);
          422  +    blob_appendf(&title, "check-in %z%S</a>", zLink, zUuid);
   411    423       if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
   412    424       fossil_free(zUuid);
          425  +    if( origCheckin ){
          426  +      zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", origCheckin);
          427  +      zLink = href("%R/info/%!S", zUuid);
          428  +      blob_appendf(&title, " and check-in %z%S</a>", zLink, zUuid);
          429  +      fossil_free(zUuid);
          430  +    }
   413    431     }else{
   414    432       blob_appendf(&title, "History of ");
   415    433       hyperlinked_path(zFilename, &title, 0, "tree", "");
   416    434       if( fShowId ) blob_appendf(&title, " (%d)", fnid);
   417    435     }
   418    436     @ <h2>%b(&title)</h2>
   419    437     blob_reset(&title);
................................................................................
   442    460       const char *zPUuid = db_column_text(&q, 5);
   443    461       const char *zUuid = db_column_text(&q, 6);
   444    462       const char *zCkin = db_column_text(&q,7);
   445    463       const char *zBgClr = db_column_text(&q, 8);
   446    464       const char *zBr = db_column_text(&q, 9);
   447    465       int fmid = db_column_int(&q, 10);
   448    466       int pfnid = db_column_int(&q, 11);
          467  +    int szFile = db_column_int(&q, 12);
   449    468       int gidx;
   450    469       char zTime[10];
   451    470       int nParent = 0;
   452    471       int aParent[GR_MAX_RAIL];
   453    472   
   454    473       db_bind_int(&qparent, ":fid", frid);
   455    474       db_bind_int(&qparent, ":mid", fmid);
................................................................................
   482    501       @ </td>
   483    502       if( zBgClr && zBgClr[0] ){
   484    503         @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
   485    504       }else{
   486    505         @ <td class="timelineTableCell">
   487    506       }
   488    507       if( zUuid ){
   489         -      if( nParent==0 ){
   490         -        @ <b>Added</b>
   491         -      }else if( pfnid ){
   492         -        char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
   493         -                                  pfnid);
   494         -        @ <b>Renamed</b> from
   495         -        @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
          508  +      if( origCheckin==0 ){
          509  +        if( nParent==0 ){
          510  +          @ <b>Added</b>
          511  +        }else if( pfnid ){
          512  +          char *zPrevName = db_text(0,"SELECT name FROM filename WHERE fnid=%d",
          513  +                                    pfnid);
          514  +          @ <b>Renamed</b> from
          515  +          @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
          516  +        }
   496    517         }
   497    518         @ %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
   498    519         if( fShowId ){
   499         -        @ (%d(frid))
          520  +        int srcId = delta_source_rid(frid);
          521  +        if( srcId>0 ){
          522  +          @ (%d(frid)&larr;%d(srcId))
          523  +        }else{
          524  +          @ (%d(frid))
          525  +        }
   500    526         }
   501    527         @ part of check-in
   502    528       }else{
   503    529         char *zNewName;
   504    530         zNewName = db_text(0,
   505    531           "SELECT name FROM filename WHERE fnid = "
   506    532           "   (SELECT fnid FROM mlink"
................................................................................
   516    542         }
   517    543       }
   518    544       hyperlink_to_uuid(zCkin);
   519    545       if( fShowId ){
   520    546         @ (%d(fmid))
   521    547       }
   522    548       @ %W(zCom) (user:
   523         -    hyperlink_to_user(zUser, zDate, "");
   524         -    @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>)
          549  +    hyperlink_to_user(zUser, zDate, ",");
          550  +    @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>,
          551  +    @ size: %d(szFile))
   525    552       if( g.perm.Hyperlink && zUuid ){
   526    553         const char *z = zFilename;
   527    554         @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
   528    555         @ [annotate]</a>
   529    556         @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
   530    557         @ [blame]</a>
   531    558         @ %z(href("%R/timeline?n=200&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
................................................................................
   567    594   
   568    595   /*
   569    596   ** WEBPAGE: mlink
   570    597   ** URL: /mlink?name=FILENAME
   571    598   ** URL: /mlink?ci=NAME
   572    599   **
   573    600   ** Show all MLINK table entries for a particular file, or for
   574         -** a particular check-in.  This screen is intended for use by developers
   575         -** in debugging Fossil.
          601  +** a particular check-in.
          602  +**
          603  +** This screen is intended for use by Fossil developers to help
          604  +** in debugging Fossil itself.  Ordinary Fossil users are not 
          605  +** expected to know what the MLINK table is or why it is important.
          606  +**
          607  +** To avoid confusing ordinary users, this page is only available
          608  +** to adminstrators.
   576    609   */
   577    610   void mlink_page(void){
   578    611     const char *zFName = P("name");
   579    612     const char *zCI = P("ci");
   580    613     Stmt q;
   581    614   
   582    615     login_check_credentials();
................................................................................
   609    642       @ <h1>MLINK table for file
   610    643       @ <a href='%R/finfo?name=%t(zFName)'>%h(zFName)</a></h1>
   611    644       @ <div class='brlist'>
   612    645       @ <table id='mlinktable'>
   613    646       @ <thead><tr>
   614    647       @ <th>Date</th>
   615    648       @ <th>Check-in</th>
   616         -    @ <th>Parent Check-in</th>
          649  +    @ <th>Parent<br>Check-in</th>
   617    650       @ <th>Merge?</th>
   618    651       @ <th>New</th>
   619    652       @ <th>Old</th>
   620         -    @ <th>Exe Bit?</th>
   621         -    @ <th>Prior Name</th>
          653  +    @ <th>Exe<br>Bit?</th>
          654  +    @ <th>Prior<br>Name</th>
   622    655       @ </tr></thead>
   623    656       @ <tbody>
   624    657       while( db_step(&q)==SQLITE_ROW ){
   625    658         const char *zDate = db_column_text(&q,0);
   626    659         const char *zCkin = db_column_text(&q,1);
   627    660         const char *zParent = db_column_text(&q,2);
   628    661         int isMerge = db_column_int(&q,3);
................................................................................
   630    663         const char *zPid = db_column_text(&q,5);
   631    664         int isExe = db_column_int(&q,7);
   632    665         const char *zPrior = db_column_text(&q,8);
   633    666         @ <tr>
   634    667         @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
   635    668         @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
   636    669         if( zParent ){
   637         -        @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
          670  +        @ <td><a href='%R/info/%!S(zParent)'>%S(zParent)</a></td>
   638    671         }else{
   639    672           @ <td><i>(New)</i></td>
   640    673         }
   641    674         @ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
   642    675         if( zFid ){
   643    676           @ <td><a href='%R/info/%!S(zFid)'>%S(zFid)</a></td>
   644    677         }else{
................................................................................
   682    715       @ <h1>MLINK table for check-in %h(zCI)</h1>
   683    716       render_checkin_context(mid, 1);
   684    717       @ <hr />
   685    718       @ <div class='brlist'>
   686    719       @ <table id='mlinktable'>
   687    720       @ <thead><tr>
   688    721       @ <th>File</th>
   689         -    @ <th>From</th>
          722  +    @ <th>Parent<br>Check-in</th>
   690    723       @ <th>Merge?</th>
   691    724       @ <th>New</th>
   692    725       @ <th>Old</th>
   693         -    @ <th>Exe Bit?</th>
   694         -    @ <th>Prior Name</th>
          726  +    @ <th>Exe<br>Bit?</th>
          727  +    @ <th>Prior<br>Name</th>
   695    728       @ </tr></thead>
   696    729       @ <tbody>
   697    730       while( db_step(&q)==SQLITE_ROW ){
   698    731         const char *zName = db_column_text(&q,0);
   699    732         const char *zFid = db_column_text(&q,1);
   700    733         const char *zPid = db_column_text(&q,3);
   701    734         const char *zPrior = db_column_text(&q,4);

Changes to src/http_transport.c.

    71     71     if( pnSent ) *pnSent = transport.nSent;
    72     72     if( pnRcvd ) *pnRcvd = transport.nRcvd;
    73     73     if( resetFlag ){
    74     74       transport.nSent = 0;
    75     75       transport.nRcvd = 0;
    76     76     }
    77     77   }
           78  +
           79  +/*
           80  +** Check zFossil to see if it is a reasonable "fossil" command to
           81  +** run on the server.  Do not allow an attacker to substitute something
           82  +** like "/bin/rm".
           83  +*/
           84  +static int is_safe_fossil_command(const char *zFossil){
           85  +  static const char *azSafe[] = { "*/fossil", "*/echo" };
           86  +  int i;
           87  +  for(i=0; i<sizeof(azSafe)/sizeof(azSafe[0]); i++){
           88  +    if( sqlite3_strglob(azSafe[i], zFossil)==0 ) return 1;
           89  +    if( strcmp(azSafe[i]+2, zFossil)==0 ) return 1;
           90  +  }
           91  +  return 0;
           92  +}
    78     93   
    79     94   /*
    80     95   ** Default SSH command
    81     96   */
    82     97   #ifdef _WIN32
    83     98   static const char zDefaultSshCmd[] = "plink -ssh -T";
    84     99   #else
................................................................................
    91    106   int transport_ssh_open(UrlData *pUrlData){
    92    107     /* For SSH we need to create and run SSH fossil http
    93    108     ** to talk to the remote machine.
    94    109     */
    95    110     char *zSsh;        /* The base SSH command */
    96    111     Blob zCmd;         /* The SSH command */
    97    112     char *zHost;       /* The host name to contact */
    98         -  int n;             /* Size of prefix string */
    99    113   
   100    114     socket_ssh_resolve_addr(pUrlData);
   101    115     zSsh = db_get("ssh-command", zDefaultSshCmd);
   102    116     blob_init(&zCmd, zSsh, -1);
   103    117     if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){
   104    118   #ifdef _WIN32
   105    119       blob_appendf(&zCmd, " -P %d", pUrlData->port);
   106    120   #else
   107    121       blob_appendf(&zCmd, " -p %d", pUrlData->port);
   108    122   #endif
   109    123     }
   110         -  if( g.fSshTrace ){
   111         -    fossil_force_newline();
   112         -    fossil_print("%s", blob_str(&zCmd));  /* Show the base of the SSH command */
   113         -  }
   114    124     if( pUrlData->user && pUrlData->user[0] ){
   115    125       zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name);
          126  +    blob_append_escaped_arg(&zCmd, zHost);
          127  +    fossil_free(zHost);
   116    128     }else{
   117         -    zHost = mprintf("%s", pUrlData->name);
          129  +    blob_append_escaped_arg(&zCmd, pUrlData->name);
   118    130     }
   119         -  n = blob_size(&zCmd);
   120         -  blob_append(&zCmd, " ", 1);
   121         -  shell_escape(&zCmd, zHost);
   122         -  blob_append(&zCmd, " ", 1);
   123         -  shell_escape(&zCmd, mprintf("%s", pUrlData->fossil));
          131  +  if( !is_safe_fossil_command(pUrlData->fossil) ){
          132  +    fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on "
          133  +                 "the server.", pUrlData->fossil);
          134  +  }
          135  +  blob_append_escaped_arg(&zCmd, pUrlData->fossil);
   124    136     blob_append(&zCmd, " test-http", 10);
   125    137     if( pUrlData->path && pUrlData->path[0] ){
   126         -    blob_append(&zCmd, " ", 1);
   127         -    shell_escape(&zCmd, mprintf("%s", pUrlData->path));
          138  +    blob_append_escaped_arg(&zCmd, pUrlData->path);
          139  +  }else{
          140  +    fossil_fatal("ssh:// URI does not specify a path to the repository");
   128    141     }
   129    142     if( g.fSshTrace ){
   130         -    fossil_print("%s\n", blob_str(&zCmd)+n);  /* Show tail of SSH command */
          143  +    fossil_print("%s\n", blob_str(&zCmd));  /* Show the whole SSH command */
   131    144     }
   132         -  free(zHost);
   133    145     popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
   134    146     if( sshPid==0 ){
   135    147       socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
   136    148     }
   137    149     blob_reset(&zCmd);
   138    150     return sshPid==0;
   139    151   }

Changes to src/info.c.

   762    762         @ </td></tr>
   763    763         @ <tr><th>Other&nbsp;Links:</th>
   764    764         @   <td>
   765    765         @     %z(href("%R/tree?ci=%!S",zUuid))files</a>
   766    766         @   | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
   767    767         @   | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
   768    768         @   | %z(href("%R/artifact/%!S",zUuid))manifest</a>
          769  +      if( g.perm.Admin ){
          770  +        @   | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
          771  +      }
   769    772         if( g.anon.Write ){
   770    773           @   | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
   771    774         }
   772    775         @   </td>
   773    776         @ </tr>
   774    777         blob_reset(&projName);
   775    778       }
................................................................................
  1069   1072   **   from=TAG        Left side of the comparison
  1070   1073   **   to=TAG          Right side of the comparison
  1071   1074   **   branch=TAG      Show all changes on a particular branch
  1072   1075   **   v=BOOLEAN       Default true.  If false, only list files that have changed
  1073   1076   **   sbs=BOOLEAN     Side-by-side diff if true.  Unified diff if false
  1074   1077   **   glob=STRING     only diff files matching this glob
  1075   1078   **   dc=N            show N lines of context around each diff
  1076         -**   w               ignore whitespace when computing diffs
         1079  +**   w=BOOLEAN       ignore whitespace when computing diffs
  1077   1080   **   nohdr           omit the description at the top of the page
  1078   1081   **
  1079   1082   **
  1080   1083   ** Show all differences between two check-ins.
  1081   1084   */
  1082   1085   void vdiff_page(void){
  1083   1086     int ridFrom, ridTo;
  1084         -  int verboseFlag = 0;
  1085         -  int sideBySide = 0;
         1087  +  int verboseFlag;
         1088  +  int sideBySide;
  1086   1089     u64 diffFlags = 0;
  1087   1090     Manifest *pFrom, *pTo;
  1088   1091     ManifestFile *pFileFrom, *pFileTo;
  1089   1092     const char *zBranch;
  1090   1093     const char *zFrom;
  1091   1094     const char *zTo;
  1092   1095     const char *zRe;
................................................................................
  1152   1155       style_submenu_element("Clear glob",
  1153   1156                             "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo,
  1154   1157                             sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW);
  1155   1158     }else{
  1156   1159       style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
  1157   1160     }
  1158   1161     if( sideBySide || verboseFlag ){
  1159         -    if( *zW ){
  1160         -      style_submenu_element("Show Whitespace Differences",
  1161         -                            "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo,
  1162         -                            sideBySide, (verboseFlag && !sideBySide)?"&v":"",
  1163         -                            zGlob ? "&glob=" : "", zGlob ? zGlob : "");
  1164         -    }else{
  1165         -      style_submenu_element("Ignore Whitespace",
  1166         -                            "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo,
  1167         -                            sideBySide, (verboseFlag && !sideBySide)?"&v":"",
  1168         -                            zGlob ? "&glob=" : "", zGlob ? zGlob : "");
  1169         -    }
         1162  +    style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
  1170   1163     }
  1171   1164     style_header("Check-in Differences");
  1172   1165     if( P("nohdr")==0 ){
  1173   1166       @ <h2>Difference From:</h2><blockquote>
  1174   1167       checkin_description(ridFrom);
  1175   1168       @ </blockquote><h2>To:</h2><blockquote>
  1176   1169       checkin_description(ridTo);
................................................................................
  1283   1276   
  1284   1277     db_prepare(&q,
  1285   1278       "SELECT filename.name, datetime(event.mtime,toLocal()),"
  1286   1279       "       coalesce(event.ecomment,event.comment),"
  1287   1280       "       coalesce(event.euser,event.user),"
  1288   1281       "       b.uuid, mlink.mperm,"
  1289   1282       "       coalesce((SELECT value FROM tagxref"
  1290         -                    "  WHERE tagid=%d AND tagtype>0 AND rid=mlink.mid),'trunk')"
         1283  +                    "  WHERE tagid=%d AND tagtype>0 AND rid=mlink.mid),'trunk'),"
         1284  +    "       a.size"
  1291   1285       "  FROM mlink, filename, event, blob a, blob b"
  1292   1286       " WHERE filename.fnid=mlink.fnid"
  1293   1287       "   AND event.objid=mlink.mid"
  1294   1288       "   AND a.rid=mlink.fid"
  1295   1289       "   AND b.rid=mlink.mid"
  1296   1290       "   AND mlink.fid=%d"
  1297   1291       "   ORDER BY filename.name, event.mtime /*sort*/",
................................................................................
  1302   1296       const char *zName = db_column_text(&q, 0);
  1303   1297       const char *zDate = db_column_text(&q, 1);
  1304   1298       const char *zCom = db_column_text(&q, 2);
  1305   1299       const char *zUser = db_column_text(&q, 3);
  1306   1300       const char *zVers = db_column_text(&q, 4);
  1307   1301       int mPerm = db_column_int(&q, 5);
  1308   1302       const char *zBr = db_column_text(&q, 6);
         1303  +    int szFile = db_column_int(&q,7);
  1309   1304       int sameFilename = prevName!=0 && fossil_strcmp(zName,prevName)==0;
  1310   1305       if( sameFilename && !showDetail ){
  1311   1306         if( cnt==1 ){
  1312   1307           @ %z(href("%R/whatis/%!S",zUuid))[more...]</a>
  1313   1308         }
  1314   1309         cnt++;
  1315   1310         continue;
................................................................................
  1346   1341         @ at
  1347   1342         hyperlink_to_date(zDate,"");
  1348   1343       }
  1349   1344       if( zBr && zBr[0] ){
  1350   1345         @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
  1351   1346       }
  1352   1347       @ &mdash; %!W(zCom) (user:
  1353         -    hyperlink_to_user(zUser,zDate,")");
         1348  +    hyperlink_to_user(zUser,zDate,",");
         1349  +    @ size: %d(szFile))
  1354   1350       if( g.perm.Hyperlink ){
  1355   1351         @ %z(href("%R/finfo?name=%T&ci=%!S",zName,zVers))[ancestry]</a>
  1356   1352         @ %z(href("%R/annotate?filename=%T&checkin=%!S",zName,zVers))
  1357   1353         @ [annotate]</a>
  1358   1354         @ %z(href("%R/blame?filename=%T&checkin=%!S",zName,zVers))
  1359   1355         @ [blame]</a>
  1360   1356       }
................................................................................
  1526   1522     }
  1527   1523     return objType;
  1528   1524   }
  1529   1525   
  1530   1526   
  1531   1527   /*
  1532   1528   ** WEBPAGE: fdiff
  1533         -** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN&regex=REGEX
         1529  +** URL: fdiff?v1=UUID&v2=UUID
  1534   1530   **
  1535         -** Two arguments, v1 and v2, identify the files to be diffed.  Show the
  1536         -** difference between the two artifacts.  Show diff side by side unless sbs
  1537         -** is 0.  Generate plain text if "patch" is present, otherwise generate
  1538         -** "pretty" HTML.
         1531  +** Two arguments, v1 and v2, identify the artifacts to be diffed.
         1532  +** Show diff side by side unless sbs is 0.  Generate plain text if
         1533  +** "patch" is present, otherwise generate "pretty" HTML.
         1534  +**
         1535  +** Alternative URL:  fdiff?from=filename1&to=filename2&ci=checkin
         1536  +**
         1537  +** If the "from" and "to" query parameters are both present, then they are
         1538  +** the names of two files within the check-in "ci" that are diffed.  If the
         1539  +** "ci" parameter is omitted, then the most recent check-in ("tip") is
         1540  +** used.
  1539   1541   **
  1540   1542   ** Additional parameters:
  1541   1543   **
  1542         -**      verbose      Show more detail when describing artifacts
  1543         -**      dc=N         Show N lines of context around each diff
  1544         -**      w            Ignore whitespace
         1544  +**      dc=N             Show N lines of context around each diff
         1545  +**      patch            Use the patch diff format
         1546  +**      regex=REGEX      Only show differences that match REGEX
         1547  +**      sbs=BOOLEAN      Turn side-by-side diffs on and off (default: on)
         1548  +**      verbose=BOOLEAN  Show more detail when describing artifacts
         1549  +**      w=BOOLEAN        Ignore whitespace
  1545   1550   */
  1546   1551   void diff_page(void){
  1547   1552     int v1, v2;
  1548         -  int isPatch;
  1549         -  int sideBySide;
         1553  +  int isPatch = P("patch")!=0;
         1554  +  int sideBySide = PB("sbs");
         1555  +  int verbose = PB("verbose");
  1550   1556     char *zV1;
  1551   1557     char *zV2;
  1552   1558     const char *zRe;
  1553         -  const char *zW;      /* URL param for ignoring whitespace */
  1554   1559     ReCompiled *pRe = 0;
  1555   1560     u64 diffFlags;
  1556   1561     u32 objdescFlags = 0;
  1557   1562   
  1558   1563     login_check_credentials();
  1559   1564     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  1560         -  v1 = name_to_rid_www("v1");
  1561         -  v2 = name_to_rid_www("v2");
         1565  +  if( P("from") && P("to") ){
         1566  +    v1 = artifact_from_ci_and_filename(0, "from");
         1567  +    v2 = artifact_from_ci_and_filename(0, "to");
         1568  +  }else{
         1569  +    Stmt q;
         1570  +    v1 = name_to_rid_www("v1");
         1571  +    v2 = name_to_rid_www("v2");
         1572  +
         1573  +    /* If the two file versions being compared both have the same
         1574  +    ** filename, then offer an "Annotate" link that constructs an
         1575  +    ** annotation between those version. */
         1576  +    db_prepare(&q,
         1577  +      "SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid),"
         1578  +      "       (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid),"
         1579  +      "       (SELECT name FROM filename WHERE filename.fnid=a.fnid)"
         1580  +      "  FROM mlink a, event ea, mlink b, event eb"
         1581  +      " WHERE a.fid=%d"
         1582  +      "   AND b.fid=%d"
         1583  +      "   AND a.fnid=b.fnid"
         1584  +      "   AND a.fid!=a.pid"
         1585  +      "   AND b.fid!=b.pid"
         1586  +      "   AND ea.objid=a.mid"
         1587  +      "   AND eb.objid=b.mid"
         1588  +      " ORDER BY ea.mtime ASC, eb.mtime ASC",
         1589  +      v1, v2
         1590  +    );
         1591  +    if( db_step(&q)==SQLITE_ROW ){
         1592  +      const char *zCkin = db_column_text(&q, 0);
         1593  +      const char *zOrig = db_column_text(&q, 1);
         1594  +      const char *zFN = db_column_text(&q, 2);
         1595  +      style_submenu_element("Annotate",
         1596  +        "%R/annotate?origin=%s&checkin=%s&filename=%T",
         1597  +        zOrig, zCkin, zFN);
         1598  +    }
         1599  +    db_finalize(&q);
         1600  +  }
  1562   1601     if( v1==0 || v2==0 ) fossil_redirect_home();
  1563   1602     zRe = P("regex");
  1564   1603     if( zRe ) re_compile(&pRe, zRe, 0);
  1565         -  if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL;
  1566         -  isPatch = P("patch")!=0;
         1604  +  if( verbose ) objdescFlags |= OBJDESC_DETAIL;
  1567   1605     if( isPatch ){
  1568   1606       Blob c1, c2, *pOut;
  1569   1607       pOut = cgi_output_blob();
  1570   1608       cgi_set_content_type("text/plain");
  1571   1609       diffFlags = 4;
  1572   1610       content_get(v1, &c1);
  1573   1611       content_get(v2, &c2);
  1574   1612       text_diff(&c1, &c2, pOut, pRe, diffFlags);
  1575   1613       blob_reset(&c1);
  1576   1614       blob_reset(&c2);
  1577   1615       return;
  1578   1616     }
  1579   1617   
  1580         -  sideBySide = !is_false(PD("sbs","1"));
  1581   1618     zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
  1582   1619     zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
  1583   1620     diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
  1584   1621   
  1585   1622     style_header("Diff");
  1586         -  zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
  1587         -  if( *zW ){
  1588         -    style_submenu_element("Show Whitespace Changes",
  1589         -                          "%s/fdiff?v1=%T&v2=%T&sbs=%d",
  1590         -                          g.zTop, P("v1"), P("v2"), sideBySide);
  1591         -  }else{
  1592         -    style_submenu_element("Ignore Whitespace",
  1593         -                          "%s/fdiff?v1=%T&v2=%T&sbs=%d&w",
  1594         -                          g.zTop, P("v1"), P("v2"), sideBySide);
  1595         -  }
         1623  +  style_submenu_checkbox("w", "Ignore Whitespace", 0, 0);
         1624  +  style_submenu_checkbox("sbs", "Side-by-Side Diff", 0, 0);
         1625  +  style_submenu_checkbox("verbose", "Verbose", 0, 0);
  1596   1626     style_submenu_element("Patch", "%s/fdiff?v1=%T&v2=%T&patch",
  1597   1627                           g.zTop, P("v1"), P("v2"));
  1598         -  if( !sideBySide ){
  1599         -    style_submenu_element("Side-by-Side Diff",
  1600         -                          "%s/fdiff?v1=%T&v2=%T&sbs=1%s",
  1601         -                          g.zTop, P("v1"), P("v2"), zW);
  1602         -  }else{
  1603         -    style_submenu_element("Unified Diff",
  1604         -                          "%s/fdiff?v1=%T&v2=%T&sbs=0%s",
  1605         -                          g.zTop, P("v1"), P("v2"), zW);
  1606         -  }
  1607   1628   
  1608   1629     if( P("smhdr")!=0 ){
  1609   1630       @ <h2>Differences From Artifact
  1610   1631       @ %z(href("%R/artifact/%!S",zV1))[%S(zV1)]</a> To
  1611   1632       @ %z(href("%R/artifact/%!S",zV2))[%S(zV2)]</a>.</h2>
  1612   1633     }else{
  1613   1634       @ <h2>Differences From
................................................................................
  1637   1658   void rawartifact_page(void){
  1638   1659     int rid = 0;
  1639   1660     char *zUuid;
  1640   1661     const char *zMime;
  1641   1662     Blob content;
  1642   1663   
  1643   1664     if( P("ci") && P("filename") ){
  1644         -    rid = artifact_from_ci_and_filename(0);
         1665  +    rid = artifact_from_ci_and_filename(0, 0);
  1645   1666     }
  1646   1667     if( rid==0 ){
  1647   1668       rid = name_to_rid_www("name");
  1648   1669     }
  1649   1670     login_check_credentials();
  1650   1671     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  1651   1672     if( rid==0 ) fossil_redirect_home();
................................................................................
  1778   1799   /*
  1779   1800   ** Look for "ci" and "filename" query parameters.  If found, try to
  1780   1801   ** use them to extract the record ID of an artifact for the file.
  1781   1802   **
  1782   1803   ** Also look for "fn" as an alias for "filename".  If either "filename"
  1783   1804   ** or "fn" is present but "ci" is missing, use "tip" as a default value
  1784   1805   ** for "ci".
         1806  +**
         1807  +** If zNameParam is not NULL, this use that parameter as the filename
         1808  +** rather than "fn" or "filename".
         1809  +**
         1810  +** If pUrl is not NULL, then record the "ci" and "filename" values in
         1811  +** pUrl.
         1812  +**
         1813  +** At least one of pUrl or zNameParam must be NULL.
  1785   1814   */
  1786         -int artifact_from_ci_and_filename(HQuery *pUrl){
         1815  +int artifact_from_ci_and_filename(HQuery *pUrl, const char *zNameParam){
  1787   1816     const char *zFilename;
  1788   1817     const char *zCI;
  1789   1818     int cirid;
  1790   1819     Manifest *pManifest;
  1791   1820     ManifestFile *pFile;
  1792   1821   
  1793         -  zFilename = P("filename");
  1794         -  if( zFilename==0 ){
  1795         -    zFilename = P("fn");
  1796         -    if( zFilename==0 ) return 0;
         1822  +  if( zNameParam ){
         1823  +    zFilename = P(zNameParam);
         1824  +  }else{
         1825  +    zFilename = P("filename");
         1826  +    if( zFilename==0 ){
         1827  +      zFilename = P("fn");
         1828  +    }
  1797   1829     }
         1830  +  if( zFilename==0 ) return 0;
         1831  +
  1798   1832     zCI = P("ci");
  1799   1833     cirid = name_to_typed_rid(zCI ? zCI : "tip", "ci");
  1800   1834     if( cirid<=0 ) return 0;
  1801   1835     pManifest = manifest_get(cirid, CFTYPE_MANIFEST, 0);
  1802   1836     if( pManifest==0 ) return 0;
  1803   1837     manifest_file_rewind(pManifest);
  1804   1838     while( (pFile = manifest_file_next(pManifest,0))!=0 ){
  1805   1839       if( fossil_strcmp(zFilename, pFile->zName)==0 ){
  1806   1840         int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", pFile->zUuid);
  1807   1841         manifest_destroy(pManifest);
  1808   1842         if( pUrl ){
         1843  +        assert( zNameParam==0 );
  1809   1844           url_add_parameter(pUrl, "fn", zFilename);
  1810   1845           if( zCI ) url_add_parameter(pUrl, "ci", zCI);
  1811   1846         }
  1812   1847         return rid;
  1813   1848       }
  1814   1849     }
  1815   1850     manifest_destroy(pManifest);
................................................................................
  1945   1980     int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
  1946   1981     int isFile = fossil_strcmp(g.zPath,"file")==0;
  1947   1982     const char *zLn = P("ln");
  1948   1983     const char *zName = P("name");
  1949   1984     HQuery url;
  1950   1985   
  1951   1986     url_initialize(&url, g.zPath);
  1952         -  rid = artifact_from_ci_and_filename(&url);
         1987  +  rid = artifact_from_ci_and_filename(&url, 0);
  1953   1988     if( rid==0 ){
  1954   1989       url_add_parameter(&url, "name", zName);
  1955   1990       if( isFile ){
  1956   1991         /* Do a top-level directory listing in /file mode if no argument
  1957   1992         ** specified */
  1958   1993         if( zName==0 || zName[0]==0 ){
  1959   1994           if( P("ci")==0 ) cgi_set_query_parameter("ci","tip");
................................................................................
  2079   2114     if( (objType & (OBJTYPE_WIKI|OBJTYPE_TICKET))!=0 ){
  2080   2115       style_submenu_element("Parsed", "%R/info/%s", zUuid);
  2081   2116     }
  2082   2117     if( descOnly ){
  2083   2118       style_submenu_element("Content", "%R/artifact/%s", zUuid);
  2084   2119     }else{
  2085   2120       if( zLn==0 || atoi(zLn)==0 ){
  2086         -      style_submenu_checkbox("ln", "Line Numbers", 0);
         2121  +      style_submenu_checkbox("ln", "Line Numbers", 0, 0);
  2087   2122       }
  2088   2123       @ <hr />
  2089   2124       content_get(rid, &content);
  2090   2125       if( renderAsWiki ){
  2091   2126         wiki_render_by_mimetype(&content, zMime);
  2092   2127       }else if( renderAsHtml ){
  2093   2128         @ <iframe src="%R/raw/%T(blob_str(&downloadName))?name=%s(zUuid)"

Changes to src/json.c.

  1261   1261     VAL(capabilities, json_cap_value());
  1262   1262     INT(g, argc);
  1263   1263     INT(g, isConst);
  1264   1264     CSTR(g, zConfigDbName);
  1265   1265     INT(g, repositoryOpen);
  1266   1266     INT(g, localOpen);
  1267   1267     INT(g, minPrefix);
  1268         -  INT(g, fNoDirSymlinks);
  1269   1268     INT(g, fSqlTrace);
  1270   1269     INT(g, fSqlStats);
  1271   1270     INT(g, fSqlPrint);
  1272   1271     INT(g, fQuiet);
  1273   1272     INT(g, fHttpTrace);
  1274   1273     INT(g, fSystemTrace);
  1275   1274     INT(g, fNoSync);

Changes to src/json_branch.c.

   293    293       fossil_fatal("Problem committing manifest: %s", g.zErrMsg);
   294    294     }
   295    295     db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
   296    296     if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
   297    297       fossil_fatal("%s", g.zErrMsg);
   298    298     }
   299    299     assert( blob_is_reset(&branch) );
   300         -  content_deltify(rootid, brid, 0);
          300  +  content_deltify(rootid, &brid, 1, 0);
   301    301     if( zNewRid ){
   302    302       *zNewRid = brid;
   303    303     }
   304    304   
   305    305     /* Commit */
   306    306     db_end_transaction(0);
   307    307   

Changes to src/main.c.

   139    139     char *zRepositoryName;  /* Name of the repository database file */
   140    140     char *zLocalDbName;     /* Name of the local database file */
   141    141     char *zOpenRevision;    /* Check-in version to use during database open */
   142    142     int localOpen;          /* True if the local database is open */
   143    143     char *zLocalRoot;       /* The directory holding the  local database */
   144    144     int minPrefix;          /* Number of digits needed for a distinct UUID */
   145    145     int eHashPolicy;        /* Current hash policy.  One of HPOLICY_* */
   146         -  int fNoDirSymlinks;     /* True if --no-dir-symlinks flag is present */
   147    146     int fSqlTrace;          /* True if --sqltrace flag is present */
   148    147     int fSqlStats;          /* True if --sqltrace or --sqlstats are present */
   149    148     int fSqlPrint;          /* True if -sqlprint flag is present */
   150    149     int fQuiet;             /* True if -quiet flag is present */
   151    150     int fJail;              /* True if running with a chroot jail */
   152    151     int fHttpTrace;         /* Trace outbound HTTP requests */
   153    152     int fAnyTrace;          /* Any kind of tracing */
................................................................................
   620    619         "another flag and is treated as such. --args FILENAME may be used\n"
   621    620         "in conjunction with any other flags.\n");
   622    621       fossil_exit(1);
   623    622     }else{
   624    623       const char *zChdir = find_option("chdir",0,1);
   625    624       g.isHTTP = 0;
   626    625       g.rcvid = 0;
   627         -    g.fNoDirSymlinks = find_option("no-dir-symlinks", 0, 0)!=0;
   628    626       g.fQuiet = find_option("quiet", 0, 0)!=0;
   629    627       g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
   630    628       g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
   631    629       g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
   632    630       g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
   633    631       g.fSshClient = 0;
   634    632       g.zSshCmd = 0;
................................................................................
   735    733     atexit( fossil_atexit );
   736    734   #ifdef FOSSIL_ENABLE_TH1_HOOKS
   737    735     /*
   738    736     ** The TH1 return codes from the hook will be handled as follows:
   739    737     **
   740    738     ** TH_OK: The xFunc() and the TH1 notification will both be executed.
   741    739     **
   742         -  ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
          740  +  ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
   743    741     **           skipped.  If the xFunc() is being hooked, the error message
   744    742     **           will be emitted.
   745    743     **
   746    744     ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
   747    745     **
   748    746     ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
   749    747     **            skipped.
................................................................................
   949    947   #if defined(FOSSIL_HAVE_FUSEFS)
   950    948     blob_appendf(pOut, "libfuse %s, loaded %s\n", fusefs_inc_version(),
   951    949                  fusefs_lib_version());
   952    950   #endif
   953    951   #if defined(FOSSIL_DEBUG)
   954    952     blob_append(pOut, "FOSSIL_DEBUG\n", -1);
   955    953   #endif
   956         -#if defined(FOSSIL_OMIT_DELTA_CKSUM_TEST)
   957         -  blob_append(pOut, "FOSSIL_OMIT_DELTA_CKSUM_TEST\n", -1);
          954  +#if defined(FOSSIL_ENABLE_DELTA_CKSUM_TEST)
          955  +  blob_append(pOut, "FOSSIL_ENABLE_DELTA_CKSUM_TEST\n", -1);
   958    956   #endif
   959    957   #if defined(FOSSIL_ENABLE_LEGACY_MV_RM)
   960    958     blob_append(pOut, "FOSSIL_ENABLE_LEGACY_MV_RM\n", -1);
   961    959   #endif
   962    960   #if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
   963    961     blob_append(pOut, "FOSSIL_ENABLE_EXEC_REL_PATHS\n", -1);
   964    962   #endif
................................................................................
  1616   1614       }
  1617   1615   #endif
  1618   1616     }
  1619   1617   
  1620   1618     /* Locate the method specified by the path and execute the function
  1621   1619     ** that implements that method.
  1622   1620     */
  1623         -  if( dispatch_name_search(g.zPath-1, CMDFLAG_WEBPAGE, &pCmd) ){
         1621  +  if( dispatch_name_search(g.zPath-1, CMDFLAG_WEBPAGE, &pCmd)
         1622  +   && dispatch_alias(g.zPath-1, &pCmd)
         1623  +  ){
  1624   1624   #ifdef FOSSIL_ENABLE_JSON
  1625   1625       if(g.json.isJsonMode){
  1626   1626         json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
  1627   1627       }else
  1628   1628   #endif
  1629   1629       {
  1630   1630   #ifdef FOSSIL_ENABLE_TH1_HOOKS
................................................................................
  1662   1662     }else{
  1663   1663   #ifdef FOSSIL_ENABLE_TH1_HOOKS
  1664   1664       /*
  1665   1665       ** The TH1 return codes from the hook will be handled as follows:
  1666   1666       **
  1667   1667       ** TH_OK: The xFunc() and the TH1 notification will both be executed.
  1668   1668       **
  1669         -    ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
         1669  +    ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
  1670   1670       **           skipped.  If the xFunc() is being hooked, the error message
  1671   1671       **           will be emitted.
  1672   1672       **
  1673   1673       ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
  1674   1674       **
  1675   1675       ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
  1676   1676       **            skipped.

Changes to src/manifest.c.

  1244   1244       db_bind_int(&s1, ":n", fnid);
  1245   1245       db_bind_int(&s1, ":pfn", pfnid);
  1246   1246       db_bind_int(&s1, ":mp", mperm);
  1247   1247       db_bind_int(&s1, ":isaux", isPrimary==0);
  1248   1248       db_exec(&s1);
  1249   1249     }
  1250   1250     if( pid && fid ){
  1251         -    content_deltify(pid, fid, 0);
         1251  +    content_deltify(pid, &fid, 1, 0);
  1252   1252     }
  1253   1253   }
  1254   1254   
  1255   1255   /*
  1256   1256   ** Do a binary search to find a file in the p->aFile[] array.
  1257   1257   **
  1258   1258   ** As an optimization, guess that the file we seek is at index p->iFile.
................................................................................
  1433   1433     }
  1434   1434   
  1435   1435     /* Try to make the parent manifest a delta from the child, if that
  1436   1436     ** is an appropriate thing to do.  For a new baseline, make the
  1437   1437     ** previous baseline a delta from the current baseline.
  1438   1438     */
  1439   1439     if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
  1440         -    content_deltify(pmid, mid, 0);
         1440  +    content_deltify(pmid, &mid, 1, 0);
  1441   1441     }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
  1442         -    content_deltify(pParent->pBaseline->rid, mid, 0);
         1442  +    content_deltify(pParent->pBaseline->rid, &mid, 1, 0);
  1443   1443     }
  1444   1444   
  1445   1445     /* Remember all children less than a few seconds younger than their parent,
  1446   1446     ** as we might want to fudge the times for those children.
  1447   1447     */
  1448   1448     if( pChild->rDate<pParent->rDate+AGE_FUDGE_WINDOW
  1449   1449         && manifest_crosslink_busy
................................................................................
  2057   2057       prior = db_int(0,
  2058   2058         "SELECT rid FROM tagxref"
  2059   2059         " WHERE tagid=%d AND mtime<%.17g"
  2060   2060         " ORDER BY mtime DESC",
  2061   2061         tagid, p->rDate
  2062   2062       );
  2063   2063       if( prior ){
  2064         -      content_deltify(prior, rid, 0);
         2064  +      content_deltify(prior, &rid, 1, 0);
  2065   2065       }
  2066   2066       if( nWiki>0 ){
  2067   2067         zComment = mprintf("Changes to wiki page [%h]", p->zWikiTitle);
  2068   2068       }else{
  2069   2069         zComment = mprintf("Deleted wiki page [%h]", p->zWikiTitle);
  2070   2070       }
  2071   2071       search_doc_touch('w',rid,p->zWikiTitle);
................................................................................
  2104   2104       subsequent = db_int(0,
  2105   2105         "SELECT rid FROM tagxref"
  2106   2106         " WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
  2107   2107         " ORDER BY mtime",
  2108   2108         tagid, p->rDate, rid
  2109   2109       );
  2110   2110       if( prior ){
  2111         -      content_deltify(prior, rid, 0);
         2111  +      content_deltify(prior, &rid, 1, 0);
  2112   2112         if( !subsequent ){
  2113   2113           db_multi_exec(
  2114   2114             "DELETE FROM event"
  2115   2115             " WHERE type='e'"
  2116   2116             "   AND tagid=%d"
  2117   2117             "   AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)",
  2118   2118             tagid, tagid
  2119   2119           );
  2120   2120         }
  2121   2121       }
  2122   2122       if( subsequent ){
  2123         -      content_deltify(rid, subsequent, 0);
         2123  +      content_deltify(rid, &subsequent, 1, 0);
  2124   2124       }else{
  2125   2125         search_doc_touch('e',rid,0);
  2126   2126         db_multi_exec(
  2127   2127           "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
  2128   2128           "VALUES('e',%.17g,%d,%d,%Q,%Q,"
  2129   2129           "  (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
  2130   2130           p->rEventDate, rid, tagid, p->zUser, p->zComment,

Changes to src/markdown.md.

     1      1   # Markdown Overview #
     2      2   
     3      3   ## Paragraphs ##
     4      4   
     5         -> Paragraphs are divided by blank lines.
            5  +> Paragraphs are divided by blank lines.  
     6      6   > End a line with two or more spaces to force a mid-paragraph line break.
     7      7   
     8      8   ## Headings ##
     9      9   
    10     10   >
    11         -    # Top-level Heading                         Alternative Top Level Heading
    12         -    # Top-level Heading Variant #               =============================
           11  +    # Top Level Heading                 Alternative Top Level Heading
           12  +    # Top Level Heading Variant #       =============================
           13  +>
           14  +    ## 2nd Level Heading                Alternative 2nd Level Heading
           15  +    ## 2nd Level Heading Variant ##     -----------------------------
    13     16   >
    14         -    ## Second-level Heading                     Alternative 2nd Level Heading
    15         -    ## Second-level Heading Variant ##          -----------------------------
           17  +    ### 3rd Level Heading               ### 3rd Level Heading Variant ###
           18  +    #### 4th Level Heading              #### 4th Level Heading Variant ####
           19  +    ##### 5th Level Heading             ##### 5th Level Heading Variant #####
           20  +    ###### 6th Level Heading            ###### 6th Level Heading Variant ######
    16     21   
    17     22   ## Links ##
    18     23   
    19     24   > 1.  **\[display text\]\(URL\)**
    20     25   > 2.  **\[display text\]\(URL "Title"\)**
    21     26   > 3.  **\[display text\]\(URL 'Title'\)**
    22     27   > 4.  **\<URL\>**
................................................................................
    70     75       > This paragraph is indented
    71     76   > >
    72     77       > > Double-indented paragraph
    73     78   
    74     79   > Begin each line with at least four spaces or one tab to produce a verbatim
    75     80   > code block.
    76     81   
           82  +## Tables ##
           83  +
           84  +>
           85  +    | Header 1     | Header 2    | Header 3      |
           86  +    ----------------------------------------------
           87  +    | Row 1 Col 1  | Row 1 Col 2 | Row 1 Col 3   |
           88  +    |:Left-aligned |:Centered   :| Right-aligned:|
           89  +    |              | ← Blank   → |               |
           90  +    | Row 4 Col 1  | Row 4 Col 2 | Row 4 Col 3   |
           91  +
           92  +> The first row is a header if followed by a horizontal rule or a blank line.
           93  +
           94  +> Placing **:** at the left, both, or right sides of a cell gives left-aligned,
           95  +> centered, or right-aligned text, respectively.  By default, header cells are
           96  +> centered, and body cells are left-aligned.
           97  +
           98  +> The leftmost **\|** is required if the first column contains at least one
           99  +> blank cell.  The rightmost **\|** is optional.
          100  +
    77    101   ## Miscellaneous ##
    78    102   
    79    103   > *   In-line images are made using **\!\[alt-text\]\(image-URL\)**.
    80         -> *   Use HTML for advanced formatting such as tables and forms.
          104  +> *   Use HTML for advanced formatting such as forms.
    81    105   > *   **\<!--** HTML-style comments **-->** are supported.
    82         -> *   Escape special characters (ex: "\[", "\(", "\*")
    83         ->     using backslash (ex: "\\\[", "\\\(", "\\\*").
          106  +> *   Escape special characters (ex: **\[** **\(** **\|** **\***)
          107  +>     using backslash (ex: **\\\[** **\\\(** **\\\|** **\\\***).
    84    108   > *   A line consisting of **---**, **\*\*\***, or **\_\_\_** is a horizontal
    85    109   >     rule.  Spaces and extra **-**/**\***/**_** are allowed.
    86    110   > *   See [daringfireball.net][] for additional information.
    87    111   > *   See this page's [Markdown source](/md_rules?txt=1) for complex examples.
    88    112   
    89    113   ## Special Features For Fossil ##
    90    114   
    91         -> *  In hyperlinks, if the URL begins with "/" then the root of the Fossil
          115  +> *  In hyperlinks, if the URL begins with **/** then the root of the Fossil
    92    116   >    repository is prepended.  This allows for repository-relative hyperlinks.
    93         -> *  For documents that begin with a top-level heading (ex: "# heading #"), the
    94         ->    heading is omitted from the body of the document and becomes the document
    95         ->    title displayed at the top of the Fossil page.
          117  +> *  For documents that begin with a top-level heading (ex: **# heading #**),
          118  +>    the heading is omitted from the body of the document and becomes the
          119  +>    document title displayed at the top of the Fossil page.
    96    120   
    97    121   [daringfireball.net]: http://daringfireball.net/projects/markdown/syntax

Changes to src/markdown_html.c.

   294    294       html_escape(ob, blob_buffer(link), blob_size(link));
   295    295     }
   296    296     BLOB_APPEND_LITERAL(ob, "</a>");
   297    297     return 1;
   298    298   }
   299    299   
   300    300   static int html_code_span(struct Blob *ob, struct Blob *text, void *opaque){
   301         -  BLOB_APPEND_LITERAL(ob, "<code>");
   302         -  html_escape(ob, blob_buffer(text), blob_size(text));
   303         -  BLOB_APPEND_LITERAL(ob, "</code>");
          301  +  if( text ){
          302  +    BLOB_APPEND_LITERAL(ob, "<code>");
          303  +    html_escape(ob, blob_buffer(text), blob_size(text));
          304  +    BLOB_APPEND_LITERAL(ob, "</code>");
          305  +  }
   304    306     return 1;
   305    307   }
   306    308   
   307    309   static int html_double_emphasis(
   308    310     struct Blob *ob,
   309    311     struct Blob *text,
   310    312     char c,

Changes to src/merge.c.

   204    204   **
   205    205   **   -f|--force              Force the merge even if it would be a no-op.
   206    206   **
   207    207   **   --force-missing         Force the merge even if there is missing content.
   208    208   **
   209    209   **   --integrate             Merged branch will be closed when committing.
   210    210   **
   211         -**   --no-dir-symlinks       Disables support for directory symlinks.
   212         -**
   213    211   **   -n|--dry-run            If given, display instead of run actions
   214    212   **
   215    213   **   -v|--verbose            Show additional details of the merge
   216    214   */
   217    215   void merge_cmd(void){
   218    216     int vid;              /* Current version "V" */
   219    217     int mid;              /* Version we are merging from "M" */

Changes to src/mkindex.c.

    11     11   **
    12     12   ** Author contact information:
    13     13   **   drh@hwaci.com
    14     14   **   http://www.hwaci.com/drh/
    15     15   **
    16     16   *******************************************************************************
    17     17   **
    18         -** This program scans Fossil source code files looking for special
    19         -** comments that indicate a command-line command or a webpage.  This
    20         -** routine collects information about these entry points and then
    21         -** generates (on standard output) C code used by Fossil to dispatch
    22         -** to those entry points.
           18  +** This utility program scans Fossil source text looking for specially
           19  +** formatted comments and generates C source code for constant tables
           20  +** that define the behavior of commands, webpages, and settings.
    23     21   **
    24     22   ** The source code is scanned for comment lines of the form:
    25     23   **
    26     24   **       WEBPAGE:  /abc/xyz
    27     25   **       COMMAND:  cmdname
           26  +**       SETTING:  access-log
    28     27   **
    29         -** These comment should be followed by a function definition of the
    30         -** form:
           28  +** The WEBPAGE and COMMAND comments should be followed by a function that
           29  +** implements the webpage or command.  The form of this function is:
    31     30   **
    32     31   **       void function_name(void){
    33     32   **
    34         -** This routine creates C source code for a constant table that maps
    35         -** command and webpage name into pointers to the function.
    36         -**
    37     33   ** Command names can divided into three classes:  1st-tier, 2nd-tier,
    38     34   ** and test.  1st-tier commands are the most frequently used and the
    39     35   ** ones that show up with "fossil help".  2nd-tier are seldom-used and/or
    40     36   ** legacy command.  Test commands are unsupported commands used for testing
    41     37   ** and analysis only.
    42     38   **
    43     39   ** Commands are 1st-tier by default.  If the command name begins with
................................................................................
    45     41   ** a test command.  If the command name has a "2nd-tier" argument or ends
    46     42   ** with a "*" character, it is second tier.  Examples:
    47     43   **
    48     44   **        COMMAND:  abcde*
    49     45   **        COMMAND:  fghij        2nd-tier
    50     46   **        COMMAND:  test-xyzzy
    51     47   **        COMMAND:  xyzzy        test
           48  +**
           49  +** A SETTING: may be followed by arguments that give additional attributes
           50  +** to that setting:
           51  +**
           52  +**        SETTING:  clean-blob   versionable width=40 block-text
           53  +**        SETTING:  auto-shun    boolean default=on
    52     54   **
    53     55   ** New arguments may be added in future releases that set additional
    54     56   ** bits in the eCmdFlags field.
    55     57   **
    56         -** Additional lines of comment after the COMMAND: or WEBPAGE: become
    57         -** the built-in help text for that command or webpage.
           58  +** Additional lines of comment after the COMMAND: or WEBPAGE: or SETTING:
           59  +** become the built-in help text for that command or webpage or setting.
    58     60   **
    59     61   ** Multiple COMMAND: entries can be attached to the same command, thus
    60     62   ** creating multiple aliases for that command.  Similarly, multiple
    61     63   ** WEBPAGE: entries can be attached to the same webpage function, to give
    62     64   ** that page aliases.
           65  +**
           66  +** For SETTING: entries, the default value for the setting can be specified
           67  +** using a default=VALUE argument if the default contains no spaces.  If the
           68  +** default value does contain spaces, use a separate line like this:
           69  +**
           70  +**        SETTING: pgp-command
           71  +**        DEFAULT: gpg --clearsign -o
           72  +**
           73  +** If no default is supplied, the default is assumed to be an empty string
           74  +** or "off" in the case of a boolean.
    63     75   */
    64     76   #include <stdio.h>
    65     77   #include <stdlib.h>
    66     78   #include <assert.h>
    67     79   #include <string.h>
    68     80   
    69     81   /***************************************************************************
    70     82   ** These macros must match similar macros in dispatch.c.
    71     83   **
    72     84   ** Allowed values for CmdOrPage.eCmdFlags. */
    73         -#define CMDFLAG_1ST_TIER  0x0001      /* Most important commands */
    74         -#define CMDFLAG_2ND_TIER  0x0002      /* Obscure and seldom used commands */
    75         -#define CMDFLAG_TEST      0x0004      /* Commands for testing only */
    76         -#define CMDFLAG_WEBPAGE   0x0008      /* Web pages */
    77         -#define CMDFLAG_COMMAND   0x0010      /* A command */
           85  +#define CMDFLAG_1ST_TIER    0x0001      /* Most important commands */
           86  +#define CMDFLAG_2ND_TIER    0x0002      /* Obscure and seldom used commands */
           87  +#define CMDFLAG_TEST        0x0004      /* Commands for testing only */
           88  +#define CMDFLAG_WEBPAGE     0x0008      /* Web pages */
           89  +#define CMDFLAG_COMMAND     0x0010      /* A command */
           90  +#define CMDFLAG_SETTING     0x0020      /* A setting */
           91  +#define CMDFLAG_VERSIONABLE 0x0040      /* A versionable setting */
           92  +#define CMDFLAG_BLOCKTEXT   0x0080      /* Multi-line text setting */
           93  +#define CMDFLAG_BOOLEAN     0x0100      /* A boolean setting */
    78     94   /**************************************************************************/
    79     95   
    80     96   /*
    81     97   ** Each entry looks like this:
    82     98   */
    83     99   typedef struct Entry {
    84    100     int eType;        /* CMDFLAG_* values */
    85    101     char *zIf;        /* Enclose in #if */
    86    102     char *zFunc;      /* Name of implementation */
    87    103     char *zPath;      /* Webpage or command name */
    88    104     char *zHelp;      /* Help text */
          105  +  char *zDflt;      /* Default value for settings */
          106  +  char *zVar;       /* config.name for settings, if different from zPath */
    89    107     int iHelp;        /* Index of Help text */
          108  +  int iWidth;       /* Display width for SETTING: values */
    90    109   } Entry;
    91    110   
    92    111   /*
    93    112   ** Maximum number of entries
    94    113   */
    95    114   #define N_ENTRY 5000
    96    115   
................................................................................
   215    234         aEntry[nUsed].eType |= CMDFLAG_1ST_TIER;
   216    235       }else if( j==8 && strncmp(&zLine[i], "2nd-tier", j)==0 ){
   217    236         aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_TEST);
   218    237         aEntry[nUsed].eType |= CMDFLAG_2ND_TIER;
   219    238       }else if( j==4 && strncmp(&zLine[i], "test", j)==0 ){
   220    239         aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_2ND_TIER);
   221    240         aEntry[nUsed].eType |= CMDFLAG_TEST;
          241  +    }else if( j==7 && strncmp(&zLine[i], "boolean", j)==0 ){
          242  +      aEntry[nUsed].eType &= ~(CMDFLAG_BLOCKTEXT);
          243  +      aEntry[nUsed].iWidth = 0;
          244  +      aEntry[nUsed].eType |= CMDFLAG_BOOLEAN;
          245  +    }else if( j==10 && strncmp(&zLine[i], "block-text", j)==0 ){
          246  +      aEntry[nUsed].eType &= ~(CMDFLAG_BOOLEAN);
          247  +      aEntry[nUsed].eType |= CMDFLAG_BLOCKTEXT;
          248  +    }else if( j==11 && strncmp(&zLine[i], "versionable", j)==0 ){
          249  +      aEntry[nUsed].eType |= CMDFLAG_VERSIONABLE;
          250  +    }else if( j>6 && strncmp(&zLine[i], "width=", 6)==0 ){
          251  +      aEntry[nUsed].iWidth = atoi(&zLine[i+6]);
          252  +    }else if( j>8 && strncmp(&zLine[i], "default=", 8)==0 ){
          253  +      aEntry[nUsed].zDflt = string_dup(&zLine[i+8], j-8);
          254  +    }else if( j>9 && strncmp(&zLine[i], "variable=", 9)==0 ){
          255  +      aEntry[nUsed].zVar = string_dup(&zLine[i+9], j-9);
   222    256       }else{
   223    257         fprintf(stderr, "%s:%d: unknown option: '%.*s'\n",
   224    258                 zFile, nLine, j, &zLine[i]);
   225    259         nErr++;
   226    260       }
   227    261     }
   228    262   
   229    263     nUsed++;
          264  +  return;
   230    265   }
   231    266   
   232    267   /*
   233    268   ** Check to see if the current line is an #if and if it is, add it to
   234    269   ** the zIf[] string.  If the current line is an #endif or #else or #elif
   235    270   ** then cancel the current zIf[] string.
   236    271   */
................................................................................
   244    279     if( strncmp(&zLine[i],"if",2)==0 ){
   245    280       zIf[0] = '#';
   246    281       memcpy(&zIf[1], &zLine[i], len+1);
   247    282     }else if( zLine[i]=='e' ){
   248    283       zIf[0] = 0;
   249    284     }
   250    285   }
          286  +
          287  +/*
          288  +** Check to see if the current line is a "** DEFAULT: ..." line for a
          289  +** SETTING definition.  If so, remember the default value.
          290  +*/
          291  +void scan_for_default(const char *zLine){
          292  +  int len;
          293  +  const char *z;
          294  +  if( nUsed<1 ) return;
          295  +  if( (aEntry[nUsed-1].eType & CMDFLAG_SETTING)==0 ) return;
          296  +  if( strncmp(zLine, "** DEFAULT: ", 12)!=0 ) return;
          297  +  z = zLine + 12;
          298  +  while( fossil_isspace(z[0]) ) z++;
          299  +  len = (int)strlen(z);
          300  +  while( len>0 && fossil_isspace(z[len-1]) ){ len--; }
          301  +  aEntry[nUsed-1].zDflt = string_dup(z,len);
          302  +}
   251    303   
   252    304   /*
   253    305   ** Scan a line for a function that implements a web page or command.
   254    306   */
   255    307   void scan_for_func(char *zLine){
   256    308     int i,j,k;
   257    309     char *z;
          310  +  int isSetting;
   258    311     if( nUsed<=nFixed ) return;
   259    312     if( strncmp(zLine, "**", 2)==0
   260    313      && fossil_isspace(zLine[2])
   261    314      && strlen(zLine)<sizeof(zHelp)-nHelp-1
   262    315      && nUsed>nFixed
   263    316      && strncmp(zLine,"** COMMAND:",11)!=0
   264    317      && strncmp(zLine,"** WEBPAGE:",11)!=0
          318  +   && strncmp(zLine,"** SETTING:",11)!=0
          319  +   && strncmp(zLine,"** DEFAULT:",11)!=0
   265    320     ){
   266    321       if( zLine[2]=='\n' ){
   267    322         zHelp[nHelp++] = '\n';
   268    323       }else{
   269    324         if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
   270    325         strcpy(&zHelp[nHelp], &zLine[3]);
   271    326         nHelp += strlen(&zHelp[nHelp]);
   272    327       }
   273    328       return;
   274    329     }
   275    330     for(i=0; fossil_isspace(zLine[i]); i++){}
   276    331     if( zLine[i]==0 ) return;
   277         -  if( strncmp(&zLine[i],"void",4)!=0 ){
   278         -    if( zLine[i]!='*' ) goto page_skip;
   279         -    return;
          332  +  isSetting = (aEntry[nFixed].eType & CMDFLAG_SETTING)!=0;
          333  +  if( !isSetting ){
          334  +    if( strncmp(&zLine[i],"void",4)!=0 ){
          335  +      if( zLine[i]!='*' ) goto page_skip;
          336  +      return;
          337  +    }
          338  +    i += 4;
          339  +    if( !fossil_isspace(zLine[i]) ) goto page_skip;
          340  +    while( fossil_isspace(zLine[i]) ){ i++; }
          341  +    for(j=0; fossil_isident(zLine[i+j]); j++){}
          342  +    if( j==0 ) goto page_skip;
   280    343     }
   281         -  i += 4;
   282         -  if( !fossil_isspace(zLine[i]) ) goto page_skip;
   283         -  while( fossil_isspace(zLine[i]) ){ i++; }
   284         -  for(j=0; fossil_isident(zLine[i+j]); j++){}
   285         -  if( j==0 ) goto page_skip;
   286    344     for(k=nHelp-1; k>=0 && fossil_isspace(zHelp[k]); k--){}
   287    345     nHelp = k+1;
   288    346     zHelp[nHelp] = 0;
   289    347     for(k=0; k<nHelp && fossil_isspace(zHelp[k]); k++){}
   290    348     if( k<nHelp ){
   291    349       z = string_dup(&zHelp[k], nHelp-k);
   292    350     }else{
   293    351       z = "";
   294    352     }
   295    353     for(k=nFixed; k<nUsed; k++){
   296    354       aEntry[k].zIf = zIf[0] ? string_dup(zIf, -1) : 0;
   297         -    aEntry[k].zFunc = string_dup(&zLine[i], j);
          355  +    aEntry[k].zFunc = isSetting ? "0" : string_dup(&zLine[i], j);
   298    356       aEntry[k].zHelp = z;
   299    357       z = 0;
   300    358       aEntry[k].iHelp = nFixed;
   301    359     }
   302         -  i+=j;
   303         -  while( fossil_isspace(zLine[i]) ){ i++; }
   304         -  if( zLine[i]!='(' ) goto page_skip;
          360  +  if( !isSetting ){
          361  +    i+=j;
          362  +    while( fossil_isspace(zLine[i]) ){ i++; }
          363  +    if( zLine[i]!='(' ) goto page_skip;
          364  +  }
   305    365     nFixed = nUsed;
   306    366     nHelp = 0;
   307    367     return;
   308    368   
   309    369   page_skip:
   310    370      for(i=nFixed; i<nUsed; i++){
   311    371         fprintf(stderr,"%s:%d: skipping page \"%s\"\n",
................................................................................
   339    399       "** This file was generated by the mkindex.exe program based on\n"
   340    400       "** comments in other Fossil source files.\n"
   341    401       "*/\n"
   342    402     );
   343    403   
   344    404     /* Output declarations for all the action functions */
   345    405     for(i=0; i<nFixed; i++){
          406  +    if( aEntry[i].eType & CMDFLAG_SETTING ) continue;
   346    407       if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
   347    408       printf("extern void %s(void);\n", aEntry[i].zFunc);
   348    409       if( aEntry[i].zIf ) printf("#endif\n");
   349    410     }
   350    411   
   351    412     /* Output strings for all the help text */
   352    413     for(i=0; i<nFixed; i++){
................................................................................
   374    435       const char *z = aEntry[i].zPath;
   375    436       int n = strlen(z);
   376    437       if( aEntry[i].zIf ){
   377    438         printf("%s", aEntry[i].zIf);
   378    439       }else if( (aEntry[i].eType & CMDFLAG_WEBPAGE)!=0 ){
   379    440         nWeb++;
   380    441       }
   381         -    printf("  { \"%.*s\",%*s%s,%*szHelp%03d, 0x%02x },\n",
          442  +    printf("  { \"%.*s\",%*s%s,%*szHelp%03d, 0x%03x },\n",
   382    443         n, z,
   383    444         25-n, "",
   384    445         aEntry[i].zFunc,
   385         -      (int)(30-strlen(aEntry[i].zFunc)), "",
          446  +      (int)(29-strlen(aEntry[i].zFunc)), "",
   386    447         aEntry[i].iHelp,
   387    448         aEntry[i].eType
   388    449       );
   389    450       if( aEntry[i].zIf ) printf("#endif\n");
   390    451     }
   391    452     printf("};\n");
   392    453     printf("#define FOSSIL_FIRST_CMD %d\n", nWeb);
          454  +
          455  +  /* Generate the aSetting[] table */
          456  +  printf("const Setting aSetting[] = {\n");
          457  +  for(i=0; i<nFixed; i++){
          458  +    const char *z;
          459  +    const char *zVar;
          460  +    const char *zDef;
          461  +    if( (aEntry[i].eType & CMDFLAG_SETTING)==0 ) continue;
          462  +    z = aEntry[i].zPath;
          463  +    zVar = aEntry[i].zVar;
          464  +    zDef = aEntry[i].zDflt;
          465  +    if( zDef==0 ) zDef = "";
          466  +    if( aEntry[i].zIf ){
          467  +      printf("%s", aEntry[i].zIf);
          468  +    }
          469  +    printf("  { \"%s\",%*s", z, (int)(20-strlen(z)), "");
          470  +    if( zVar ){
          471  +      printf(" \"%s\",%*s", zVar, (int)(15-strlen(zVar)), "");
          472  +    }else{
          473  +      printf(" 0,%*s", 16, "");
          474  +    }
          475  +    printf(" %3d, %d, %d, \"%s\"%*s },\n",
          476  +      aEntry[i].iWidth,
          477  +      (aEntry[i].eType & CMDFLAG_VERSIONABLE)!=0,
          478  +      (aEntry[i].eType & CMDFLAG_BLOCKTEXT)!=0,
          479  +      zDef, (int)(10-strlen(zDef)), ""
          480  +    );
          481  +    if( aEntry[i].zIf ){
          482  +      printf("#endif\n");
          483  +    }
          484  +  }
          485  +  printf("};\n");
          486  +
   393    487   }
   394    488   
   395    489   /*
   396    490   ** Process a single file of input
   397    491   */
   398    492   void process_file(void){
   399    493     FILE *in = fopen(zFile, "r");
................................................................................
   405    499     nLine = 0;
   406    500     while( fgets(zLine, sizeof(zLine), in) ){
   407    501       nLine++;
   408    502       scan_for_if(zLine);
   409    503       scan_for_label("WEBPAGE:",zLine,CMDFLAG_WEBPAGE);
   410    504       scan_for_label("COMMAND:",zLine,CMDFLAG_COMMAND);
   411    505       scan_for_func(zLine);
          506  +    scan_for_label("SETTING:",zLine,CMDFLAG_SETTING);
          507  +    scan_for_default(zLine);
   412    508     }
   413    509     fclose(in);
   414    510     nUsed = nFixed;
   415    511   }
   416    512   
   417    513   int main(int argc, char **argv){
   418    514     int i;

Changes to src/mkversion.c.

     6      6   **     ./a.out manifest.uuid manifest VERSION
     7      7   **
     8      8   ** Note that the manifest.uuid and manifest files are generated by Fossil.
     9      9   */
    10     10   #include <stdio.h>
    11     11   #include <string.h>
    12     12   #include <stdlib.h>
           13  +
           14  +static FILE *open_for_reading(const char *zFilename){
           15  +  FILE *f = fopen(zFilename, "r");
           16  +  if( f==0 ){
           17  +    fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
           18  +    exit(1);
           19  +  }
           20  +  return f;
           21  +}
    13     22   
    14     23   int main(int argc, char *argv[]){
    15     24       FILE *m,*u,*v;
    16     25       char *z;
    17     26   #if defined(__DMC__)            /* e.g. 0x857 */
    18     27       int i = 0;
    19     28   #endif
    20     29       int j = 0, x = 0, d = 0;
    21     30       int vn[3];
    22     31       char b[1000];
    23     32       char vx[1000];
           33  +    if( argc!=4 ){
           34  +      fprintf(stderr, "Usage: %s manifest.uuid manifest VERSION\n", argv[0]);
           35  +      exit(1);
           36  +    }
    24     37       memset(b,0,sizeof(b));
    25     38       memset(vx,0,sizeof(vx));
    26         -    u = fopen(argv[1],"r");
           39  +    u = open_for_reading(argv[1]);
    27     40       if( fgets(b, sizeof(b)-1,u)==0 ){
    28     41         fprintf(stderr, "malformed manifest.uuid file: %s\n", argv[1]);
    29     42         exit(1);
    30     43       }
    31     44       fclose(u);
    32     45       for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
    33     46       *z = 0;
    34     47       printf("#define MANIFEST_UUID \"%s\"\n",b);
    35     48       printf("#define MANIFEST_VERSION \"[%10.10s]\"\n",b);
    36         -    m = fopen(argv[2],"r");
           49  +    m = open_for_reading(argv[2]);
    37     50       while(b ==  fgets(b, sizeof(b)-1,m)){
    38     51           if(0 == strncmp("D ",b,2)){
    39     52               printf("#define MANIFEST_DATE \"%.10s %.8s\"\n",b+2,b+13);
    40     53               printf("#define MANIFEST_YEAR \"%.4s\"\n",b+2);
    41     54           }
    42     55       }
    43     56       fclose(m);
    44         -    v = fopen(argv[3],"r");
           57  +    v = open_for_reading(argv[3]);
    45     58       if( fgets(b, sizeof(b)-1,v)==0 ){
    46     59         fprintf(stderr, "malformed VERSION file: %s\n", argv[3]);
    47     60         exit(1);
    48     61       }
    49     62       fclose(v);
    50     63       for(z=b; z[0] && z[0]!='\r' && z[0]!='\n'; z++){}
    51     64       *z = 0;

Changes to src/name.c.

  1005   1005     char *zSha1Bg;
  1006   1006     char *zSha3Bg;
  1007   1007   
  1008   1008     login_check_credentials();
  1009   1009     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  1010   1010     style_header("List Of Artifacts");
  1011   1011     style_submenu_element("250 Largest", "bigbloblist");
         1012  +  if( g.perm.Admin ){
         1013  +    style_submenu_element("Artifact Log", "rcvfromlist");
         1014  +  }
  1012   1015     if( !unpubOnly && mx>n && P("s")==0 ){
  1013   1016       int i;
  1014   1017       @ <p>Select a range of artifacts to view:</p>
  1015   1018       @ <ul>
  1016   1019       for(i=1; i<=mx; i+=n){
  1017   1020         @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n))
  1018   1021         @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a>
................................................................................
  1075   1078   */
  1076   1079   void bigbloblist_page(void){
  1077   1080     Stmt q;
  1078   1081     int n = atoi(PD("n","250"));
  1079   1082   
  1080   1083     login_check_credentials();
  1081   1084     if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
         1085  +  if( g.perm.Admin ){
         1086  +    style_submenu_element("Artifact Log", "rcvfromlist");
         1087  +  }
         1088  +  style_submenu_element("All Artifacts", "bloblist");
  1082   1089     style_header("%d Largest Artifacts", n);
  1083   1090     db_multi_exec(
  1084   1091       "CREATE TEMP TABLE toshow(rid INTEGER PRIMARY KEY);"
  1085   1092       "INSERT INTO toshow(rid)"
  1086   1093       "  SELECT rid FROM blob"
  1087   1094       "   ORDER BY length(content) DESC"
  1088   1095       "   LIMIT %d;", n

Changes to src/path.c.

    43     43   */
    44     44   static struct {
    45     45     PathNode *pCurrent;   /* Current generation of nodes */
    46     46     PathNode *pAll;       /* All nodes */
    47     47     Bag seen;             /* Nodes seen before */
    48     48     int nStep;            /* Number of steps from first to last */
    49     49     PathNode *pStart;     /* Earliest node */
    50         -  PathNode *pPivot;     /* Common ancestor of pStart and pEnd */
    51     50     PathNode *pEnd;       /* Most recent */
    52     51   } path;
    53     52   
    54     53   /*
    55     54   ** Return the first (last) element of the computed path.
    56     55   */
    57     56   PathNode *path_first(void){ return path.pStart; }
................................................................................
   191    190   PathNode *path_midpoint(void){
   192    191     PathNode *p;
   193    192     int i;
   194    193     if( path.nStep<2 ) return 0;
   195    194     for(p=path.pEnd, i=0; p && i<path.nStep/2; p=p->pFrom, i++){}
   196    195     return p;
   197    196   }
          197  +
          198  +/*
          199  +** Compute the shortest path between two check-ins and then transfer
          200  +** that path into the "ancestor" table.  This is a utility used by
          201  +** both /annotate and /finfo.  See also: compute_direct_ancestors().
          202  +*/
          203  +void path_shortest_stored_in_ancestor_table(
          204  +  int origid,     /* RID for check-in at start of the path */
          205  +  int cid         /* RID for check-in at the end of the path */
          206  +){
          207  +  PathNode *pPath;
          208  +  int gen = 0;
          209  +  Stmt ins;
          210  +  pPath = path_shortest(cid, origid, 1, 0);
          211  +  db_multi_exec(
          212  +    "CREATE TEMP TABLE IF NOT EXISTS ancestor("
          213  +    "  rid INT UNIQUE,"
          214  +    "  generation INTEGER PRIMARY KEY"
          215  +    ");"
          216  +    "DELETE FROM ancestor;"
          217  +  );
          218  +  db_prepare(&ins, "INSERT INTO ancestor(rid, generation) VALUES(:rid,:gen)");
          219  +  while( pPath ){
          220  +    db_bind_int(&ins, ":rid", pPath->rid);
          221  +    db_bind_int(&ins, ":gen", ++gen);
          222  +    db_step(&ins);
          223  +    db_reset(&ins);
          224  +    pPath = pPath->u.pTo;
          225  +  }
          226  +  db_finalize(&ins);
          227  +  path_reset();
          228  +}
   198    229   
   199    230   /*
   200    231   ** COMMAND: test-shortest-path
   201    232   **
   202    233   ** Usage: %fossil test-shortest-path ?--no-merge? VERSION1 VERSION2
   203    234   **
   204    235   ** Report the shortest path between two check-ins.  If the --no-merge flag

Changes to src/pivot.c.

   161    161   **
   162    162   ** Options:
   163    163   **    --ignore-merges       Ignore merges for discovering name pivots
   164    164   */
   165    165   void test_find_pivot(void){
   166    166     int i, rid;
   167    167     int ignoreMerges = find_option("ignore-merges",0,0)!=0;
          168  +  int showDetails = find_option("details",0,0)!=0;
   168    169     if( g.argc<4 ){
   169    170       usage("?options? PRIMARY SECONDARY ...");
   170    171     }
   171    172     db_must_be_within_tree();
   172    173     pivot_set_primary(name_to_rid(g.argv[2]));
   173    174     for(i=3; i<g.argc; i++){
   174    175       pivot_set_secondary(name_to_rid(g.argv[i]));
   175    176     }
   176    177     rid = pivot_find(ignoreMerges);
   177    178     printf("pivot=%s\n",
   178    179            db_text("?","SELECT uuid FROM blob WHERE rid=%d",rid)
   179    180     );
          181  +  if( showDetails ){
          182  +    Stmt q;
          183  +    db_prepare(&q,
          184  +      "SELECT substr(uuid,1,12), aqueue.rid, datetime(aqueue.mtime),"
          185  +             " aqueue.pending, aqueue.src\n"
          186  +      "  FROM aqueue JOIN blob ON aqueue.rid=blob.rid\n"
          187  +      " ORDER BY aqueue.mtime DESC"
          188  +    );
          189  +    while( db_step(&q)==SQLITE_ROW ){
          190  +      printf("\"%s\",%d,\"%s\",%d,%d\n",
          191  +        db_column_text(&q, 0),
          192  +        db_column_int(&q, 1),
          193  +        db_column_text(&q, 2),
          194  +        db_column_int(&q, 3),
          195  +        db_column_int(&q, 4));
          196  +    }
          197  +    db_finalize(&q);
          198  +  }
   180    199   }

Changes to src/printf.c.

    59     59       if( nDigitHuman > 40 ) nDigitHuman = 40;
    60     60       nDigitUrl = nDigitHuman + 6;
    61     61       if( nDigitUrl < FOSSIL_HASH_DIGITS_URL ) nDigitUrl = FOSSIL_HASH_DIGITS_URL;
    62     62       if( nDigitUrl > 40 ) nDigitUrl = 40;
    63     63     }
    64     64     return bForUrl ? nDigitUrl : nDigitHuman;
    65     65   }
           66  +
           67  +/*
           68  +** Return the number of characters in a %S output.
           69  +*/
           70  +int length_of_S_display(void){
           71  +  return hashDigits(0);
           72  +}
    66     73   
    67     74   /*
    68     75   ** Conversion types fall into various categories as defined by the
    69     76   ** following enumeration.
    70     77   */
    71     78   #define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
    72     79   #define etFLOAT       2 /* Floating point.  %f */

Changes to src/rebuild.c.

   445    445     if(!g.fQuiet && ttyOutput ){
   446    446       percent_complete(1000);
   447    447       fossil_print("\n");
   448    448     }
   449    449     return errCnt;
   450    450   }
   451    451   
          452  +/*
          453  +** Number of neighbors to search
          454  +*/
          455  +#define N_NEIGHBOR 5
          456  +
   452    457   /*
   453    458   ** Attempt to convert more full-text blobs into delta-blobs for
   454    459   ** storage efficiency.
   455    460   */
   456    461   void extra_deltification(void){
   457    462     Stmt q;
   458         -  int topid, previd, rid;
          463  +  int aPrev[N_NEIGHBOR];
          464  +  int nPrev;
          465  +  int rid;
   459    466     int prevfnid, fnid;
   460    467     db_begin_transaction();
          468  +
          469  +  /* Look for manifests that have not been deltaed and try to make them
          470  +  ** children of one of the 5 chronologically subsequent check-ins
          471  +  */
   461    472     db_prepare(&q,
   462    473        "SELECT rid FROM event, blob"
   463    474        " WHERE blob.rid=event.objid"
   464    475        "   AND event.type='ci'"
   465    476        "   AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
   466    477        " ORDER BY event.mtime DESC"
   467    478     );
   468         -  topid = previd = 0;
          479  +  nPrev = 0;
   469    480     while( db_step(&q)==SQLITE_ROW ){
   470    481       rid = db_column_int(&q, 0);
   471         -    if( topid==0 ){
   472         -      topid = previd = rid;
          482  +    if( nPrev>0 ){
          483  +      content_deltify(rid, aPrev, nPrev, 0);
          484  +    }
          485  +    if( nPrev<N_NEIGHBOR ){
          486  +      aPrev[nPrev++] = rid;
   473    487       }else{
   474         -      if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
   475         -        content_deltify(rid, topid, 0);
   476         -      }
   477         -      previd = rid;
          488  +      int i;
          489  +      for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
          490  +      aPrev[N_NEIGHBOR-1] = rid;
   478    491       }
   479    492     }
   480    493     db_finalize(&q);
   481    494   
          495  +  /* For individual files that have not been deltaed, try to find
          496  +  ** a parent which is an undeltaed file with the same name in a
          497  +  ** more recent branch.
          498  +  */
   482    499     db_prepare(&q,
   483         -     "SELECT blob.rid, mlink.fnid FROM blob, mlink, plink"
          500  +     "SELECT DISTINCT blob.rid, mlink.fnid FROM blob, mlink, plink"
   484    501        " WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
   485    502        "   AND mlink.fid=blob.rid"
   486    503        "   AND mlink.mid=plink.cid"
   487    504        "   AND plink.cid=mlink.mid"
   488    505        " ORDER BY mlink.fnid, plink.mtime DESC"
   489    506     );
   490    507     prevfnid = 0;
   491    508     while( db_step(&q)==SQLITE_ROW ){
   492    509       rid = db_column_int(&q, 0);
   493    510       fnid = db_column_int(&q, 1);
   494         -    if( prevfnid!=fnid ){
   495         -      prevfnid = fnid;
   496         -      topid = previd = rid;
          511  +    if( fnid!=prevfnid ) nPrev = 0;
          512  +    prevfnid = fnid;
          513  +    if( nPrev>0 ){
          514  +      content_deltify(rid, aPrev, nPrev, 0);
          515  +    }
          516  +    if( nPrev<N_NEIGHBOR ){
          517  +      aPrev[nPrev++] = rid;
   497    518       }else{
   498         -      if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
   499         -        content_deltify(rid, topid, 0);
   500         -      }
   501         -      previd = rid;
          519  +      int i;
          520  +      for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
          521  +      aPrev[N_NEIGHBOR-1] = rid;
   502    522       }
   503    523     }
   504    524     db_finalize(&q);
   505    525   
   506    526     db_end_transaction(0);
   507    527   }
   508    528   

Changes to src/search.c.

   631    631     blob_reset(&sql);
   632    632     print_timeline(&q, nLimit, width, 0);
   633    633     db_finalize(&q);
   634    634   }
   635    635   
   636    636   #if INTERFACE
   637    637   /* What to search for */
   638         -#define SRCH_CKIN   0x0001    /* Search over check-in comments */
   639         -#define SRCH_DOC    0x0002    /* Search over embedded documents */
   640         -#define SRCH_TKT    0x0004    /* Search over tickets */
   641         -#define SRCH_WIKI   0x0008    /* Search over wiki */
   642         -#define SRCH_ALL    0x000f    /* Search over everything */
          638  +#define SRCH_CKIN     0x0001    /* Search over check-in comments */
          639  +#define SRCH_DOC      0x0002    /* Search over embedded documents */
          640  +#define SRCH_TKT      0x0004    /* Search over tickets */
          641  +#define SRCH_WIKI     0x0008    /* Search over wiki */
          642  +#define SRCH_TECHNOTE 0x0010    /* Search over tech notes */
          643  +#define SRCH_ALL      0x001f    /* Search over everything */
   643    644   #endif
   644    645   
   645    646   /*
   646    647   ** Remove bits from srchFlags which are disallowed by either the
   647    648   ** current server configuration or by user permissions.
   648    649   */
   649    650   unsigned int search_restrict(unsigned int srchFlags){
   650    651     static unsigned int knownGood = 0;
   651    652     static unsigned int knownBad = 0;
   652    653     static const struct { unsigned m; const char *zKey; } aSetng[] = {
   653         -     { SRCH_CKIN,   "search-ci"   },
   654         -     { SRCH_DOC,    "search-doc"  },
   655         -     { SRCH_TKT,    "search-tkt"  },
   656         -     { SRCH_WIKI,   "search-wiki" },
          654  +     { SRCH_CKIN,     "search-ci"   },
          655  +     { SRCH_DOC,      "search-doc"  },
          656  +     { SRCH_TKT,      "search-tkt"  },
          657  +     { SRCH_WIKI,     "search-wiki" },
          658  +     { SRCH_TECHNOTE, "search-technote" },
   657    659     };
   658    660     int i;
   659         -  if( g.perm.Read==0 )   srchFlags &= ~(SRCH_CKIN|SRCH_DOC);
          661  +  if( g.perm.Read==0 )   srchFlags &= ~(SRCH_CKIN|SRCH_DOC|SRCH_TECHNOTE);
   660    662     if( g.perm.RdTkt==0 )  srchFlags &= ~(SRCH_TKT);
   661    663     if( g.perm.RdWiki==0 ) srchFlags &= ~(SRCH_WIKI);
   662    664     for(i=0; i<count(aSetng); i++){
   663    665       unsigned int m = aSetng[i].m;
   664    666       if( (srchFlags & m)==0 ) continue;
   665    667       if( ((knownGood|knownBad) & m)!=0 ) continue;
   666    668       if( db_get_boolean(aSetng[i].zKey,0) ){
................................................................................
   768    770         "         search_score(),"
   769    771         "         't'||tkt_id,"
   770    772         "         datetime(tkt_mtime),"
   771    773         "         search_snippet()"
   772    774         "    FROM ticket"
   773    775         "   WHERE search_match(title('t',tkt_id,NULL),body('t',tkt_id,NULL));"
   774    776       );
          777  +  }
          778  +  if( (srchFlags & SRCH_TECHNOTE)!=0 ){
          779  +    db_multi_exec(
          780  +      "WITH technote(uuid,rid,mtime) AS ("
          781  +      "  SELECT substr(tagname,7), tagxref.rid, max(tagxref.mtime)"
          782  +      "    FROM tag, tagxref"
          783  +      "   WHERE tag.tagname GLOB 'event-*'"
          784  +      "     AND tagxref.tagid=tag.tagid"
          785  +      "   GROUP BY 1"
          786  +      ")"
          787  +      "INSERT INTO x(label,url,score,id,date,snip)"
          788  +      "  SELECT printf('Tech Note: %%s',uuid),"
          789  +      "         printf('/technote/%%s',uuid),"
          790  +      "         search_score(),"
          791  +      "         'e'||rid,"
          792  +      "         datetime(mtime),"
          793  +      "         search_snippet()"
          794  +      "    FROM technote"
          795  +      "   WHERE search_match('',body('e',rid,NULL));"
          796  +    );
   775    797     }
   776    798   }
   777    799   
   778    800   /*
   779    801   ** Number of significant bits in a u32
   780    802   */
   781    803   static int nbits(u32 x){
................................................................................
   884    906       "  WHERE ftsidx MATCH %Q"
   885    907       "    AND ftsdocs.rowid=ftsidx.docid",
   886    908       zPattern
   887    909     );
   888    910     if( srchFlags!=SRCH_ALL ){
   889    911       const char *zSep = " AND (";
   890    912       static const struct { unsigned m; char c; } aMask[] = {
   891         -       { SRCH_CKIN,  'c' },
   892         -       { SRCH_DOC,   'd' },
   893         -       { SRCH_TKT,   't' },
   894         -       { SRCH_WIKI,  'w' },
          913  +       { SRCH_CKIN,     'c' },
          914  +       { SRCH_DOC,      'd' },
          915  +       { SRCH_TKT,      't' },
          916  +       { SRCH_WIKI,     'w' },
          917  +       { SRCH_TECHNOTE, 'e' },
   895    918       };
   896    919       int i;
   897    920       for(i=0; i<count(aMask); i++){
   898    921         if( srchFlags & aMask[i].m ){
   899    922           blob_appendf(&sql, "%sftsdocs.type='%c'", zSep, aMask[i].c);
   900    923           zSep = " OR ";
   901    924         }
................................................................................
  1035   1058     const char *zClass = 0;
  1036   1059     const char *zDisable1;
  1037   1060     const char *zDisable2;
  1038   1061     const char *zPattern;
  1039   1062     int fDebug = PB("debug");
  1040   1063     srchFlags = search_restrict(srchFlags);
  1041   1064     switch( srchFlags ){
  1042         -    case SRCH_CKIN:  zType = " Check-ins";  zClass = "Ckin";  break;
  1043         -    case SRCH_DOC:   zType = " Docs";       zClass = "Doc";   break;
  1044         -    case SRCH_TKT:   zType = " Tickets";    zClass = "Tkt";   break;
  1045         -    case SRCH_WIKI:  zType = " Wiki";       zClass = "Wiki";  break;
         1065  +    case SRCH_CKIN:     zType = " Check-ins";  zClass = "Ckin"; break;
         1066  +    case SRCH_DOC:      zType = " Docs";       zClass = "Doc";  break;
         1067  +    case SRCH_TKT:      zType = " Tickets";    zClass = "Tkt";  break;
         1068  +    case SRCH_WIKI:     zType = " Wiki";       zClass = "Wiki"; break;
         1069  +    case SRCH_TECHNOTE: zType = " Tech Notes"; zClass = "Note"; break;
  1046   1070     }
  1047   1071     if( srchFlags==0 ){
  1048   1072       zDisable1 = " disabled";
  1049   1073       zDisable2 = " disabled";
  1050   1074       zPattern = "";
  1051   1075     }else{
  1052   1076       zDisable1 = " autofocus";
................................................................................
  1058   1082       @ <div class='searchForm searchForm%s(zClass)'>
  1059   1083     }else{
  1060   1084       @ <div class='searchForm'>
  1061   1085     }
  1062   1086     @ <input type="text" name="s" size="40" value="%h(zPattern)"%s(zDisable1)>
  1063   1087     if( useYparam && (srchFlags & (srchFlags-1))!=0 && useYparam ){
  1064   1088       static const struct { char *z; char *zNm; unsigned m; } aY[] = {
  1065         -       { "all",  "All",        SRCH_ALL  },
  1066         -       { "c",    "Check-ins",  SRCH_CKIN },
  1067         -       { "d",    "Docs",       SRCH_DOC  },
  1068         -       { "t",    "Tickets",    SRCH_TKT  },
  1069         -       { "w",    "Wiki",       SRCH_WIKI },
         1089  +       { "all",  "All",        SRCH_ALL      },
         1090  +       { "c",    "Check-ins",  SRCH_CKIN     },
         1091  +       { "d",    "Docs",       SRCH_DOC      },
         1092  +       { "t",    "Tickets",    SRCH_TKT      },
         1093  +       { "w",    "Wiki",       SRCH_WIKI     },
         1094  +       { "e",    "Tech Notes", SRCH_TECHNOTE },
  1070   1095       };
  1071   1096       const char *zY = PD("y","all");
  1072   1097       unsigned newFlags = srchFlags;
  1073   1098       int i;
  1074   1099       @ <select size='1' name='y'>
  1075   1100       for(i=0; i<count(aY); i++){
  1076   1101         if( (aY[i].m & srchFlags)==0 ) continue;
................................................................................
  1114   1139   **
  1115   1140   **    s=PATTERN       Specify the full-text pattern to search for
  1116   1141   **    y=TYPE          What to search.
  1117   1142   **                      c -> check-ins
  1118   1143   **                      d -> documentation
  1119   1144   **                      t -> tickets
  1120   1145   **                      w -> wiki
         1146  +**                      e -> tech notes
  1121   1147   **                    all -> everything
  1122   1148   */
  1123   1149   void search_page(void){
  1124   1150     login_check_credentials();
  1125   1151     style_header("Search");
  1126   1152     search_screen(SRCH_ALL, 1);
  1127   1153     style_footer();
................................................................................
  1220   1246   ** Return "search text" - a reduced version of a document appropriate for
  1221   1247   ** full text search and/or for constructing a search result snippet.
  1222   1248   **
  1223   1249   **    cType:            d      Embedded documentation
  1224   1250   **                      w      Wiki page
  1225   1251   **                      c      Check-in comment
  1226   1252   **                      t      Ticket text
         1253  +**                      e      Tech note
  1227   1254   **
  1228   1255   **    rid               The RID of an artifact that defines the object
  1229   1256   **                      being searched.
  1230   1257   **
  1231   1258   **    zName             Name of the object being searched.  This is used
  1232   1259   **                      only to help figure out the mimetype (text/plain,
  1233   1260   **                      test/html, test/x-fossil-wiki, or text/x-markdown)
................................................................................
  1245   1272         Blob doc;
  1246   1273         content_get(rid, &doc);
  1247   1274         blob_to_utf8_no_bom(&doc, 0);
  1248   1275         get_stext_by_mimetype(&doc, mimetype_from_name(zName), pOut);
  1249   1276         blob_reset(&doc);
  1250   1277         break;
  1251   1278       }
         1279  +    case 'e':     /* Tech Notes */
  1252   1280       case 'w': {   /* Wiki */
  1253         -      Manifest *pWiki = manifest_get(rid, CFTYPE_WIKI,0);
         1281  +      Manifest *pWiki = manifest_get(rid,
         1282  +          cType == 'e' ? CFTYPE_EVENT : CFTYPE_WIKI, 0);
  1254   1283         Blob wiki;
  1255   1284         if( pWiki==0 ) break;
  1256   1285         blob_init(&wiki, pWiki->zWiki, -1);
  1257   1286         get_stext_by_mimetype(&wiki, wiki_filter_mimetypes(pWiki->zMimetype),
  1258   1287                               pOut);
  1259   1288         blob_reset(&wiki);
  1260   1289         manifest_destroy(pWiki);
................................................................................
  1365   1394   
  1366   1395   /*
  1367   1396   ** COMMAND: test-search-stext
  1368   1397   **
  1369   1398   ** Usage: fossil test-search-stext TYPE RID NAME
  1370   1399   **
  1371   1400   ** Compute the search text for document TYPE-RID whose name is NAME.
  1372         -** The TYPE is one of "c", "d", "t", or "w".  The RID is the document
         1401  +** The TYPE is one of "c", "d", "t", "w", or "e".  The RID is the document
  1373   1402   ** ID.  The NAME is used to figure out a mimetype to use for formatting
  1374   1403   ** the raw document text.
  1375   1404   */
  1376   1405   void test_search_stext(void){
  1377   1406     Blob out;
  1378   1407     db_find_and_open_repository(0,0);
  1379   1408     if( g.argc!=5 ) usage("TYPE RID NAME");
................................................................................
  1482   1511       ") INSERT OR IGNORE INTO ftsdocs(type,rid,name,idxed)"
  1483   1512       "     SELECT 'w', rid, name, 0 FROM latest_wiki;"
  1484   1513     );
  1485   1514     db_multi_exec(
  1486   1515       "INSERT OR IGNORE INTO ftsdocs(type,rid,idxed)"
  1487   1516       "  SELECT 't', tkt_id, 0 FROM ticket;"
  1488   1517     );
         1518  +  db_multi_exec(
         1519  +    "INSERT OR IGNORE INTO ftsdocs(type,rid,name,idxed)"
         1520  +    "  SELECT 'e', objid, comment, 0 FROM event WHERE type='e';"
         1521  +  );
  1489   1522   }
  1490   1523   
  1491   1524   /*
  1492   1525   ** The document described by cType,rid,zName is about to be added or
  1493   1526   ** updated.  If the document has already been indexed, then unindex it
  1494   1527   ** now while we still have access to the old content.  Add the document
  1495   1528   ** to the queue of documents that need to be indexed or reindexed.
................................................................................
  1506   1539          zType, rid
  1507   1540       );
  1508   1541       db_multi_exec(
  1509   1542          "REPLACE INTO ftsdocs(type,rid,name,idxed)"
  1510   1543          " VALUES(%Q,%d,%Q,0)",
  1511   1544          zType, rid, zName
  1512   1545       );
  1513         -    if( cType=='w' ){
         1546  +    if( cType=='w' || cType=='e' ){
  1514   1547         db_multi_exec(
  1515   1548           "DELETE FROM ftsidx WHERE docid IN"
  1516         -        "    (SELECT rowid FROM ftsdocs WHERE type='w' AND name=%Q AND idxed)",
  1517         -        zName
         1549  +        "    (SELECT rowid FROM ftsdocs WHERE type='%c' AND name=%Q AND idxed)",
         1550  +        cType, zName
  1518   1551         );
  1519   1552         db_multi_exec(
  1520         -        "DELETE FROM ftsdocs WHERE type='w' AND name=%Q AND rid!=%d",
  1521         -        zName, rid
         1553  +        "DELETE FROM ftsdocs WHERE type='%c' AND name=%Q AND rid!=%d",
         1554  +        cType, zName, rid
  1522   1555         );
  1523   1556       }
  1524   1557     }
  1525   1558   }
  1526   1559   
  1527   1560   /*
  1528   1561   ** If the doc-glob and doc-br settings are valid for document search
................................................................................
  1645   1678       "            'Wiki: '||ftsdocs.name,"
  1646   1679       "            '/wiki?name='||urlencode(ftsdocs.name),"
  1647   1680       "            tagxref.mtime"
  1648   1681       "       FROM tagxref WHERE tagxref.rid=ftsdocs.rid)"
  1649   1682       " WHERE ftsdocs.type='w' AND NOT ftsdocs.idxed"
  1650   1683     );
  1651   1684   }
         1685  +
         1686  +/*
         1687  +** Deal with all of the unindexed 'e' terms in FTSDOCS
         1688  +*/
         1689  +static void search_update_technote_index(void){
         1690  +  db_multi_exec(
         1691  +    "INSERT INTO ftsidx(docid,title,body)"
         1692  +    " SELECT rowid, title('e',rid,NULL),body('e',rid,NULL) FROM ftsdocs"
         1693  +    "  WHERE type='e' AND NOT idxed;"
         1694  +  );
         1695  +  if( db_changes()==0 ) return;
         1696  +  db_multi_exec(
         1697  +    "UPDATE ftsdocs SET idxed=1,"
         1698  +    "  (name,label,url,mtime) = "
         1699  +    "    (SELECT ftsdocs.name,"
         1700  +    "            'Tech Note: '||ftsdocs.name,"
         1701  +    "            '/technote/'||substr(tag.tagname,7),"
         1702  +    "            tagxref.mtime"
         1703  +    "       FROM tagxref, tag USING (tagid)"
         1704  +    "      WHERE tagxref.rid=ftsdocs.rid"
         1705  +    "        AND tagname GLOB 'event-*')"
         1706  +    " WHERE ftsdocs.type='e' AND NOT ftsdocs.idxed"
         1707  +  );
         1708  +}
  1652   1709   
  1653   1710   /*
  1654   1711   ** Deal with all of the unindexed entries in the FTSDOCS table - that
  1655   1712   ** is to say, all the entries with FTSDOCS.IDXED=0.  Add them to the
  1656   1713   ** index.
  1657   1714   */
  1658   1715   void search_update_index(unsigned int srchFlags){
................................................................................
  1665   1722     }
  1666   1723     if( srchFlags & SRCH_TKT ){
  1667   1724       search_update_ticket_index();
  1668   1725     }
  1669   1726     if( srchFlags & SRCH_WIKI ){
  1670   1727       search_update_wiki_index();
  1671   1728     }
         1729  +  if( srchFlags & SRCH_TECHNOTE ){
         1730  +    search_update_technote_index();
         1731  +  }
  1672   1732   }
  1673   1733   
  1674   1734   /*
  1675   1735   ** Construct, prepopulate, and then update the full-text index.
  1676   1736   */
  1677   1737   void search_rebuild_index(void){
  1678   1738     fossil_print("rebuilding the search index...");
................................................................................
  1692   1752   ** of the repository.  Subcommands:
  1693   1753   **
  1694   1754   **     reindex            Rebuild the search index.  This is a no-op if
  1695   1755   **                        index search is disabled
  1696   1756   **
  1697   1757   **     index (on|off)     Turn the search index on or off
  1698   1758   **
  1699         -**     enable cdtw        Enable various kinds of search. c=Check-ins,
  1700         -**                        d=Documents, t=Tickets, w=Wiki.
         1759  +**     enable cdtwe       Enable various kinds of search. c=Check-ins,
         1760  +**                        d=Documents, t=Tickets, w=Wiki, e=Tech Notes.
  1701   1761   **
  1702         -**     disable cdtw       Disable various kinds of search
         1762  +**     disable cdtwe      Disable various kinds of search
  1703   1763   **
  1704   1764   **     stemmer (on|off)   Turn the Porter stemmer on or off for indexed
  1705   1765   **                        search.  (Unindexed search is never stemmed.)
  1706   1766   **
  1707   1767   ** The current search settings are displayed after any changes are applied.
  1708   1768   ** Run this command with no arguments to simply see the settings.
  1709   1769   */
................................................................................
  1712   1772        { 1,  "reindex"  },
  1713   1773        { 2,  "index"    },
  1714   1774        { 3,  "disable"  },
  1715   1775        { 4,  "enable"   },
  1716   1776        { 5,  "stemmer"  },
  1717   1777     };
  1718   1778     static const struct { char *zSetting; char *zName; char *zSw; } aSetng[] = {
  1719         -     { "search-ckin",   "check-in search:",  "c" },
  1720         -     { "search-doc",    "document search:",  "d" },
  1721         -     { "search-tkt",    "ticket search:",    "t" },
  1722         -     { "search-wiki",   "wiki search:",      "w" },
         1779  +     { "search-ckin",     "check-in search:",  "c" },
         1780  +     { "search-doc",      "document search:",  "d" },
         1781  +     { "search-tkt",      "ticket search:",    "t" },
         1782  +     { "search-wiki",     "wiki search:",      "w" },
         1783  +     { "search-technote", "tech note search:", "e" },
  1723   1784     };
  1724   1785     char *zSubCmd = 0;
  1725   1786     int i, j, n;
  1726   1787     int iCmd = 0;
  1727   1788     int iAction = 0;
  1728   1789     db_find_and_open_repository(0, 0);
  1729   1790     if( g.argc>2 ){
................................................................................
  1777   1838     }
  1778   1839     if( iAction>=2 ){
  1779   1840       search_rebuild_index();
  1780   1841     }
  1781   1842   
  1782   1843     /* Always show the status before ending */
  1783   1844     for(i=0; i<count(aSetng); i++){
  1784         -    fossil_print("%-16s %s\n", aSetng[i].zName,
         1845  +    fossil_print("%-17s %s\n", aSetng[i].zName,
  1785   1846          db_get_boolean(aSetng[i].zSetting,0) ? "on" : "off");
  1786   1847     }
  1787         -  fossil_print("%-16s %s\n", "Porter stemmer:",
         1848  +  fossil_print("%-17s %s\n", "Porter stemmer:",
  1788   1849          db_get_boolean("search-stemmer",0) ? "on" : "off");
  1789   1850     if( search_index_exists() ){
  1790         -    fossil_print("%-16s enabled\n", "full-text index:");
  1791         -    fossil_print("%-16s %d\n", "documents:",
         1851  +    fossil_print("%-17s enabled\n", "full-text index:");
         1852  +    fossil_print("%-17s %d\n", "documents:",
  1792   1853          db_int(0, "SELECT count(*) FROM ftsdocs"));
  1793   1854     }else{
  1794         -    fossil_print("%-16s disabled\n", "full-text index:");
         1855  +    fossil_print("%-17s disabled\n", "full-text index:");
  1795   1856     }
  1796   1857     db_end_transaction(0);
  1797   1858   }
  1798   1859   
  1799   1860   /*
  1800   1861   ** WEBPAGE: test-ftsdocs
  1801   1862   **

Changes to src/setup.c.

    94     94     setup_menu_entry("Login-Group", "setup_login_group",
    95     95       "Manage single sign-on between this repository and others"
    96     96       " on the same server");
    97     97     setup_menu_entry("Tickets", "tktsetup",
    98     98       "Configure the trouble-ticketing system for this repository");
    99     99     setup_menu_entry("Search","srchsetup",
   100    100       "Configure the built-in search engine");
          101  +  setup_menu_entry("URL Aliases", "waliassetup",
          102  +    "Configure URL aliases");
   101    103     setup_menu_entry("Transfers", "xfersetup",
   102    104       "Configure the transfer system for this repository");
   103    105     setup_menu_entry("Skins", "setup_skin",
   104    106       "Select and/or modify the web interface \"skins\"");
   105    107     setup_menu_entry("Moderation", "setup_modreq",
   106    108       "Enable/Disable requiring moderator approval of Wiki and/or Ticket"
   107    109       " changes and attachments.");
................................................................................
  1219   1221     @ might not work inside a chroot() jail.
  1220   1222     @ (Property: "max-loadavg")</p>
  1221   1223   
  1222   1224     @ <hr />
  1223   1225     onoff_attribute(
  1224   1226         "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
  1225   1227         "auto-hyperlink", "autohyperlink", 1, 0);
  1226         -  @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
  1227         -  @ including user "nobody", as long as (1) the User-Agent string in the
         1228  +  @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users,
         1229  +  @ including user "nobody", as long as
         1230  +  @ <ol><li>the User-Agent string in the
  1228   1231     @ HTTP header indicates that the request is coming from an actual human
  1229         -  @ being and not a robot or spider and (2) the user agent is able to
  1230         -  @ run Javascript in order to set the href= attribute of hyperlinks.  Bots
  1231         -  @ and spiders can forge a User-Agent string that makes them seem to be a
  1232         -  @ normal browser and they can run javascript just like browsers.  But most
  1233         -  @ bots do not go to that much trouble so this is normally an effective
  1234         -  @ defense.<p>
         1232  +  @ being, and
         1233  +  @ <li>the user agent is able to
         1234  +  @ run Javascript in order to set the href= attribute of hyperlinks, and
         1235  +  @ <li>mouse movement is detected (optional - see the checkbox below), and
         1236  +  @ <li>a number of milliseconds have passed since the page loaded.</ol>
  1235   1237     @
  1236         -  @ <p>You do not normally want a bot to walk your entire repository because
         1238  +  @ <p>This setting is designed to give easy access to humans while
         1239  +  @ keeping out robots and spiders.
         1240  +  @ You do not normally want a robot to walk your entire repository because
  1237   1241     @ if it does, your server will end up computing diffs and annotations for
  1238   1242     @ every historical version of every file and creating ZIPs and tarballs of
  1239   1243     @ every historical check-in, which can use a lot of CPU and bandwidth
  1240   1244     @ even for relatively small projects.</p>
  1241   1245     @
  1242   1246     @ <p>Additional parameters that control this behavior:</p>
  1243   1247     @ <blockquote>
  1244         -  onoff_attribute("Enable hyperlinks for humans as deduced from the UserAgent "
  1245         -                  "string", "auto-hyperlink-ishuman", "ahis", 0, 0);
  1246         -  @ <br />
  1247   1248     onoff_attribute("Require mouse movement before enabling hyperlinks",
  1248   1249                     "auto-hyperlink-mouseover", "ahmo", 0, 0);
  1249   1250     @ <br />
  1250   1251     entry_attribute("Delay in milliseconds before enabling hyperlinks", 5,
  1251         -                  "auto-hyperlink-delay", "ah-delay", "10", 0);
         1252  +                  "auto-hyperlink-delay", "ah-delay", "50", 0);
  1252   1253     @ </blockquote>
  1253         -  @ <p>Hyperlinks for user "nobody" are normally enabled as soon as the page
  1254         -  @ finishes loading.  But the first check-box below can be set to require mouse
  1255         -  @ movement before enabling the links. One can also set a delay prior to enabling
  1256         -  @ links by enter a positive number of milliseconds in the entry box above.</p>
  1257         -  @ (Properties: "auto-hyperlink", "auto-hyperlink-ishuman",
         1254  +  @ <p>For maximum robot defense, the "require mouse movement" should
         1255  +  @ be turned on and the "Delay" should be at least 50 milliseconds.</p>
         1256  +  @ (Properties: "auto-hyperlink",
  1258   1257     @ "auto-hyperlink-mouseover", and "auto-hyperlink-delay")</p>
  1259   1258   
  1260   1259     @ <hr />
  1261   1260     onoff_attribute("Require a CAPTCHA if not logged in",
  1262   1261                     "require-captcha", "reqcapt", 1, 0);
  1263   1262     @ <p>Require a CAPTCHA for edit operations (appending, creating, or
  1264   1263     @ editing wiki or tickets or adding attachments to wiki or tickets)
................................................................................
  1403   1402       @ </table>
  1404   1403       @
  1405   1404       @ <p><form action="%s(g.zTop)/setup_login_group" method="post"><div>
  1406   1405       login_insert_csrf_secret();
  1407   1406       @ To leave this login group press
  1408   1407       @ <input type="submit" value="Leave Login Group" name="leave">
  1409   1408       @ </form></p>
         1409  +    @ <br />For best results, use the same number of <a href="setup_access#ipt">
         1410  +    @ IP octets</a> in the login cookie across all repositories in the
         1411  +    @ same Login Group.
  1410   1412       @ <hr /><h2>Implementation Details</h2>
  1411   1413       @ <p>The following are fields from the CONFIG table related to login-groups,
  1412   1414       @ provided here for instructional and debugging purposes:</p>
  1413   1415       @ <table border='1' id='configTab'>
  1414         -    @ <thead><tr><th>Config.Name<th>Config.Value<th>Config.mtime</tr></thead><tbody>
         1416  +    @ <thead><tr>
         1417  +    @ <th>Config.Name<th>Config.Value<th>Config.mtime</tr>
         1418  +    @ </thead><tbody>
  1415   1419       db_prepare(&q, "SELECT name, value, datetime(mtime,'unixepoch') FROM config"
  1416   1420                      " WHERE name GLOB 'peer-*'"
  1417   1421                      "    OR name GLOB 'project-*'"
         1422  +                   "    OR name GLOB 'login-group-*'"
  1418   1423                      " ORDER BY name");
  1419   1424       while( db_step(&q)==SQLITE_ROW ){
  1420   1425         @ <tr><td>%h(db_column_text(&q,0))</td>
  1421   1426         @ <td>%h(db_column_text(&q,1))</td>
  1422   1427         @ <td>%h(db_column_text(&q,2))</td></tr>
  1423   1428       }
  1424   1429       db_finalize(&q);
................................................................................
  1532   1537   /*
  1533   1538   ** WEBPAGE: setup_settings
  1534   1539   **
  1535   1540   ** Change or view miscellaneous settings.  Part of the
  1536   1541   ** Admin pages requiring Admin privileges.
  1537   1542   */
  1538   1543   void setup_settings(void){
         1544  +  int nSetting;
         1545  +  int i;
  1539   1546     Setting const *pSet;
         1547  +  const Setting *aSetting = setting_info(&nSetting);
  1540   1548   
  1541   1549     login_check_credentials();
  1542   1550     if( !g.perm.Setup ){
  1543   1551       login_needed(0);
  1544   1552       return;
  1545   1553     }
  1546   1554   
................................................................................
  1547   1555     style_header("Settings");
  1548   1556     if(!g.repositoryOpen){
  1549   1557       /* Provide read-only access to versioned settings,
  1550   1558          but only if no repo file was explicitly provided. */
  1551   1559       db_open_local(0);
  1552   1560     }
  1553   1561     db_begin_transaction();
  1554         -  @ <p>This page provides a simple interface to the "fossil setting" command.
  1555         -  @ See the "fossil help setting" output below for further information on
  1556         -  @ the meaning of each setting.</p><hr />
         1562  +  @ <p>Settings marked with (v) are "versionable" and will be overridden
         1563  +  @ by the contents of managed files named
         1564  +  @ "<tt>.fossil-settings/</tt><i>SETTING-NAME</i>".
         1565  +  @ If the file for a versionable setting exists, the value cannot be
         1566  +  @ changed on this screen.</p><hr /><p>
         1567  +  @
  1557   1568     @ <form action="%s(g.zTop)/setup_settings" method="post"><div>
  1558   1569     @ <table border="0"><tr><td valign="top">
  1559   1570     login_insert_csrf_secret();
  1560         -  for(pSet=aSetting; pSet->name!=0; pSet++){
         1571  +  for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
  1561   1572       if( pSet->width==0 ){
  1562   1573         int hasVersionableValue = pSet->versionable &&
  1563   1574             (db_get_versioned(pSet->name, NULL)!=0);
  1564         -      onoff_attribute(pSet->name, pSet->name,
         1575  +      onoff_attribute("", pSet->name,
  1565   1576                         pSet->var!=0 ? pSet->var : pSet->name,
  1566   1577                         is_truth(pSet->def), hasVersionableValue);
         1578  +      @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
  1567   1579         if( pSet->versionable ){
  1568   1580           @  (v)<br />
  1569   1581         } else {
  1570   1582           @ <br />
  1571   1583         }
  1572   1584       }
  1573   1585     }
  1574   1586     @ <br /><input type="submit"  name="submit" value="Apply Changes" />
  1575   1587     @ </td><td style="width:50px;"></td><td valign="top">
  1576         -  for(pSet=aSetting; pSet->name!=0; pSet++){
  1577         -    if( pSet->width!=0 && !pSet->versionable && !pSet->forceTextArea ){
  1578         -      entry_attribute(pSet->name, /*pSet->width*/ 25, pSet->name,
         1588  +  for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
         1589  +    if( pSet->width!=0 && !pSet->forceTextArea ){
         1590  +      int hasVersionableValue = pSet->versionable &&
         1591  +          (db_get_versioned(pSet->name, NULL)!=0);
         1592  +      entry_attribute("", /*pSet->width*/ 25, pSet->name,
  1579   1593                         pSet->var!=0 ? pSet->var : pSet->name,
  1580         -                      (char*)pSet->def, 0);
  1581         -      @ <br />
  1582         -    }
  1583         -  }
  1584         -  for(pSet=aSetting; pSet->name!=0; pSet++){
  1585         -    if( pSet->width!=0 && !pSet->versionable && pSet->forceTextArea ){
  1586         -      @<b>%s(pSet->name)</b><br />
  1587         -      textarea_attribute("", /*rows*/ 3, /*cols*/ 50, pSet->name,
  1588         -                      pSet->var!=0 ? pSet->var : pSet->name,
  1589         -                      (char*)pSet->def, 0);
  1590         -      @ <br />
         1594  +                      (char*)pSet->def, hasVersionableValue);
         1595  +      @ <a href='%R/help?cmd=%s(pSet->name)'>%h(pSet->name)</a>
         1596  +      if( pSet->versionable ){
         1597  +        @  (v)<br />
         1598  +      } else {
         1599  +        @ <br />
         1600  +      }
  1591   1601       }
  1592   1602     }
  1593   1603     @ </td><td style="width:50px;"></td><td valign="top">
  1594         -  for(pSet=aSetting; pSet->name!=0; pSet++){
  1595         -    if( pSet->width!=0 && pSet->versionable ){
         1604  +  for(i=0, pSet=aSetting; i<nSetting; i++, pSet++){
         1605  +    if( pSet->width!=0 && pSet->forceTextArea ){
  1596   1606         int hasVersionableValue = db_get_versioned(pSet->name, NULL)!=0;
  1597         -      @<b>%s(pSet->name)</b> (v)<br />
  1598         -      textarea_attribute("", /*rows*/ 3, /*cols*/ 20, pSet->name,
         1607  +      @ <a href='%R/help?cmd=%s(pSet->name)'>%s(pSet->name)</a>
         1608  +      if( pSet->versionable ){
         1609  +        @  (v)<br />
         1610  +      } else {
         1611  +        @ <br />
         1612  +      }
         1613  +      textarea_attribute("", /*rows*/ 2, /*cols*/ 35, pSet->name,
  1599   1614                         pSet->var!=0 ? pSet->var : pSet->name,
  1600   1615                         (char*)pSet->def, hasVersionableValue);
  1601   1616         @<br />
  1602   1617       }
  1603   1618     }
  1604   1619     @ </td></tr></table>
  1605   1620     @ </div></form>
  1606         -  @ <p>Settings marked with (v) are 'versionable' and will be overridden
  1607         -  @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>
  1608         -  @ in the check-out root.
  1609         -  @ If such a file is present, the corresponding field above is not
  1610         -  @ editable.</p><hr /><p>
  1611         -  @ These settings work the same as the
  1612         -  @ <a href='%R/help?cmd=settings'>fossil set</a> command.
  1613   1621     db_end_transaction(0);
  1614   1622     style_footer();
  1615   1623   }
  1616   1624   
  1617   1625   /*
  1618   1626   ** WEBPAGE: setup_config
  1619   1627   **
................................................................................
  1777   1785     textarea_attribute("", 6, 80, "adunit-right", "adright", "", 0);
  1778   1786     @ <br />
  1779   1787     onoff_attribute("Omit ads to administrator",
  1780   1788        "adunit-omit-if-admin", "oia", 0, 0);
  1781   1789     @ <br />
  1782   1790     onoff_attribute("Omit ads to logged-in users",
  1783   1791        "adunit-omit-if-user", "oiu", 0, 0);
         1792  +  @ <br />
         1793  +  onoff_attribute("Temporarily disable all ads",
         1794  +     "adunit-disable", "oall", 0, 0);
  1784   1795     @ <br />
  1785   1796     @ <input type="submit" name="submit" value="Apply Changes" />
  1786   1797     @ <input type="submit" name="clear" value="Delete Ad-Unit" />
  1787   1798     @ </div></form>
  1788   1799     @ <hr />
  1789   1800     @ <b>Ad-Unit Notes:</b><ul>
  1790   1801     @ <li>Leave both Ad-Units blank to disable all advertising.
................................................................................
  2152   2163       }else{
  2153   2164         @ <pre class="th1error">%h(zR)</pre>
  2154   2165       }
  2155   2166     }
  2156   2167     style_footer();
  2157   2168   }
  2158   2169   
  2159         -static void admin_log_render_limits(){
  2160         -  int const count = db_int(0,"SELECT COUNT(*) FROM admin_log");
  2161         -  int i;
  2162         -  int limits[] = {
  2163         -  10, 20, 50, 100, 250, 500, 0
  2164         -  };
  2165         -  for(i = 0; limits[i]; ++i ){
  2166         -    cgi_printf("%s<a href='?n=%d'>%d</a>",
  2167         -               i ? " " : "",
  2168         -               limits[i], limits[i]);
  2169         -    if(limits[i]>count) break;
  2170         -  }
  2171         -}
  2172         -
  2173   2170   /*
  2174   2171   ** WEBPAGE: admin_log
  2175   2172   **
  2176   2173   ** Shows the contents of the admin_log table, which is only created if
  2177   2174   ** the admin-log setting is enabled. Requires Admin or Setup ('a' or
  2178   2175   ** 's') permissions.
  2179   2176   */
  2180   2177   void page_admin_log(){
  2181         -  Stmt stLog = empty_Stmt;
  2182         -  Blob qLog = empty_blob;
  2183         -  int limit;
         2178  +  Stmt stLog;
         2179  +  int limit;                 /* How many entries to show */
         2180  +  int ofst;                  /* Offset to the first entry */
  2184   2181     int fLogEnabled;
  2185   2182     int counter = 0;
  2186   2183     login_check_credentials();
  2187   2184     if( !g.perm.Setup && !g.perm.Admin ){
  2188   2185       login_needed(0);
  2189   2186       return;
  2190   2187     }
  2191   2188     style_header("Admin Log");
  2192   2189     create_admin_log_table();
  2193         -  limit = atoi(PD("n","20"));
         2190  +  limit = atoi(PD("n","200"));
         2191  +  ofst = atoi(PD("x","0"));
  2194   2192     fLogEnabled = db_get_boolean("admin-log", 0);
  2195   2193     @ <div>Admin logging is %s(fLogEnabled?"on":"off").
  2196   2194     @ (Change this on the <a href="setup_settings">settings</a> page.)</div>
  2197   2195   
  2198         -
  2199         -  @ <div>Limit results to: <span>
  2200         -  admin_log_render_limits();
  2201         -  @ </span></div>
  2202         -
  2203         -  blob_append_sql(&qLog,
  2204         -               "SELECT datetime(time,'unixepoch'), who, page, what "
  2205         -               "FROM admin_log "
  2206         -               "ORDER BY time DESC ");
  2207         -  if(limit>0){
  2208         -    @ %d(limit) Most recent entries:
  2209         -    blob_append_sql(&qLog, "LIMIT %d", limit);
         2196  +  if( ofst>0 ){
         2197  +    int prevx = ofst - limit;
         2198  +    if( prevx<0 ) prevx = 0;
         2199  +    @ <p><a href="admin_log?n=%d(limit)&x=%d(prevx)">[Newer]</a></p>
  2210   2200     }
  2211         -  db_prepare(&stLog, "%s", blob_sql_text(&qLog));
  2212         -  blob_reset(&qLog);
         2201  +  db_prepare(&stLog,
         2202  +    "SELECT datetime(time,'unixepoch'), who, page, what "
         2203  +    "FROM admin_log "
         2204  +    "ORDER BY time DESC");
         2205  +
  2213   2206     @ <table id="adminLogTable" class="adminLogTable" width="100%%">
  2214   2207     @ <thead>
  2215   2208     @ <th>Time</th>
  2216   2209     @ <th>User</th>
  2217   2210     @ <th>Page</th>
  2218   2211     @ <th width="60%%">Message</th>
  2219   2212     @ </thead><tbody>
  2220   2213     while( SQLITE_ROW == db_step(&stLog) ){
  2221   2214       const char *zTime = db_column_text(&stLog, 0);
  2222   2215       const char *zUser = db_column_text(&stLog, 1);
  2223   2216       const char *zPage = db_column_text(&stLog, 2);
  2224   2217       const char *zMessage = db_column_text(&stLog, 3);
  2225         -    @ <tr class="row%d(counter++%2)">
         2218  +    counter++;
         2219  +    if( counter<ofst ) continue;
         2220  +    if( counter>ofst+limit ) break;
         2221  +    @ <tr class="row%d(counter%2)">
  2226   2222       @ <td class="adminTime">%s(zTime)</td>
  2227   2223       @ <td>%s(zUser)</td>
  2228   2224       @ <td>%s(zPage)</td>
  2229   2225       @ <td>%h(zMessage)</td>
  2230   2226       @ </tr>
  2231   2227     }
  2232   2228     @ </tbody></table>
  2233         -  if(limit>0 && counter<limit){
  2234         -    @ <div>%d(counter) entries shown.</div>
         2229  +  if( counter>ofst+limit ){
         2230  +    @ <p><a href="admin_log?n=%d(limit)&x=%d(limit+ofst)">[Older]</a></p>
  2235   2231     }
         2232  +
         2233  +  output_table_sorting_javascript("adminLogTable", "Tttx", 1);
  2236   2234     style_footer();
  2237   2235   }
  2238   2236   
  2239   2237   /*
  2240   2238   ** WEBPAGE: srchsetup
  2241   2239   **
  2242   2240   ** Configure the search engine.  Requires Admin privilege.
................................................................................
  2278   2276     @ <hr />
  2279   2277     onoff_attribute("Search Check-in Comments", "search-ci", "sc", 0, 0);
  2280   2278     @ <br />
  2281   2279     onoff_attribute("Search Documents", "search-doc", "sd", 0, 0);
  2282   2280     @ <br />
  2283   2281     onoff_attribute("Search Tickets", "search-tkt", "st", 0, 0);
  2284   2282     @ <br />
  2285         -  onoff_attribute("Search Wiki","search-wiki", "sw", 0, 0);
         2283  +  onoff_attribute("Search Wiki", "search-wiki", "sw", 0, 0);
         2284  +  @ <br />
         2285  +  onoff_attribute("Search Tech Notes", "search-technote", "se", 0, 0);
  2286   2286     @ <hr />
  2287   2287     @ <p><input type="submit"  name="submit" value="Apply Changes" /></p>
  2288   2288     @ <hr />
  2289   2289     if( P("fts0") ){
  2290   2290       search_drop_index();
  2291   2291     }else if( P("fts1") ){
  2292   2292       search_drop_index();
................................................................................
  2306   2306       @ larger repositories.</p>
  2307   2307       onoff_attribute("Use Porter Stemmer","search-stemmer","ss",0,0);
  2308   2308       @ <p><input type="submit" name="fts1" value="Create A Full-Text Index">
  2309   2309     }
  2310   2310     @ </div></form>
  2311   2311     style_footer();
  2312   2312   }
         2313  +
         2314  +/*
         2315  +** A URL Alias originally called zOldName is now zNewName/zValue.
         2316  +** Write SQL to make this change into pSql.
         2317  +**
         2318  +** If zNewName or zValue is an empty string, then delete the entry.
         2319  +**
         2320  +** If zOldName is an empty string, create a new entry.
         2321  +*/
         2322  +static void setup_update_url_alias(
         2323  +  Blob *pSql,
         2324  +  const char *zOldName,
         2325  +  const char *zNewName,
         2326  +  const char *zValue
         2327  +){
         2328  +  if( zNewName[0]==0 || zValue[0]==0 ){
         2329  +    if( zOldName[0] ){
         2330  +      blob_append_sql(pSql,
         2331  +        "DELETE FROM config WHERE name='walias:%q';\n",
         2332  +        zOldName);
         2333  +    }
         2334  +    return;
         2335  +  }
         2336  +  if( zOldName[0]==0 ){
         2337  +    blob_append_sql(pSql,
         2338  +      "INSERT INTO config(name,value,mtime) VALUES('walias:%q',%Q,now());\n",
         2339  +      zNewName, zValue);
         2340  +    return;
         2341  +  }
         2342  +  if( strcmp(zOldName, zNewName)!=0 ){
         2343  +    blob_append_sql(pSql,
         2344  +       "UPDATE config SET name='walias:%q', value=%Q, mtime=now()"
         2345  +       " WHERE name='walias:%q';\n",
         2346  +       zNewName, zValue, zOldName);
         2347  +  }else{
         2348  +    blob_append_sql(pSql,
         2349  +       "UPDATE config SET value=%Q, mtime=now()"
         2350  +       " WHERE name='walias:%q' AND value<>%Q;\n",
         2351  +       zValue, zOldName, zValue);
         2352  +  }
         2353  +}
         2354  +
         2355  +/*
         2356  +** WEBPAGE: waliassetup
         2357  +**
         2358  +** Configure the URL aliases
         2359  +*/
         2360  +void page_waliassetup(){
         2361  +  Stmt q;
         2362  +  int cnt = 0;
         2363  +  Blob namelist;
         2364  +  login_check_credentials();
         2365  +  if( !g.perm.Setup && !g.perm.Admin ){
         2366  +    login_needed(0);
         2367  +    return;
         2368  +  }
         2369  +  style_header("URL Alias Configuration");
         2370  +  if( P("submit")!=0 ){
         2371  +    Blob token;
         2372  +    Blob sql;
         2373  +    const char *zNewName;
         2374  +    const char *zValue;
         2375  +    char zCnt[10];
         2376  +    login_verify_csrf_secret();
         2377  +    blob_init(&namelist, PD("namelist",""), -1);
         2378  +    blob_init(&sql, 0, 0);
         2379  +    while( blob_token(&namelist, &token) ){
         2380  +      const char *zOldName = blob_str(&token);
         2381  +      sqlite3_snprintf(sizeof(zCnt), zCnt, "n%d", cnt);
         2382  +      zNewName = PD(zCnt, "");
         2383  +      sqlite3_snprintf(sizeof(zCnt), zCnt, "v%d", cnt);
         2384  +      zValue = PD(zCnt, "");
         2385  +      setup_update_url_alias(&sql, zOldName, zNewName, zValue);
         2386  +      cnt++;
         2387  +      blob_reset(&token);
         2388  +    }
         2389  +    sqlite3_snprintf(sizeof(zCnt), zCnt, "n%d", cnt);
         2390  +    zNewName = PD(zCnt,"");
         2391  +    sqlite3_snprintf(sizeof(zCnt), zCnt, "v%d", cnt);
         2392  +    zValue = PD(zCnt,"");
         2393  +    setup_update_url_alias(&sql, "", zNewName, zValue);
         2394  +    db_multi_exec("%s", blob_sql_text(&sql));
         2395  +    blob_reset(&sql);
         2396  +    blob_reset(&namelist);
         2397  +    cnt = 0;
         2398  +  }
         2399  +  db_prepare(&q,
         2400  +      "SELECT substr(name,8), value FROM config WHERE name GLOB 'walias:/*'"
         2401  +      " UNION ALL SELECT '', ''"
         2402  +  );
         2403  +  @ <form action="%s(g.zTop)/waliassetup" method="post"><div>
         2404  +  login_insert_csrf_secret();
         2405  +  @ <table border=0 cellpadding=5>
         2406  +  @ <tr><th>Alias<th>URI That The Alias Maps Into
         2407  +  blob_init(&namelist, 0, 0);
         2408  +  while( db_step(&q)==SQLITE_ROW ){
         2409  +    const char *zName = db_column_text(&q, 0);
         2410  +    const char *zValue = db_column_text(&q, 1);
         2411  +    @ <tr><td>
         2412  +    @ <input type='text' size='20' value='%h(zName)' name='n%d(cnt)'>
         2413  +    @ </td><td>
         2414  +    @ <input type='text' size='80' value='%h(zValue)' name='v%d(cnt)'>
         2415  +    @ </td></tr>
         2416  +    cnt++;
         2417  +    if( blob_size(&namelist)>0 ) blob_append(&namelist, " ", 1);
         2418  +    blob_append(&namelist, zName, -1);
         2419  +  }
         2420  +  db_finalize(&q);
         2421  +  @ <tr><td>
         2422  +  @ <input type='hidden' name='namelist' value='%h(blob_str(&namelist))'>
         2423  +  @ <input type='submit' name='submit' value="Apply Changes">
         2424  +  @ </td><td></td></tr>
         2425  +  @ </table></form>
         2426  +  @ <hr>
         2427  +  @ <p>When the first term of an incoming URL exactly matches one of the "Aliases" on
         2428  +  @ the left-hand side (LHS) above, the URL is converted into the corresponding form
         2429  +  @ on the right-hand side (RHS).
         2430  +  @ <ul>
         2431  +  @ <li><p>
         2432  +  @ The LHS is compared against only the first term of the incoming URL.
         2433  +  @ All LHS entries in the alias table should therefore begin with a
         2434  +  @ single "/" followed by a single path element.
         2435  +  @ <li><p>
         2436  +  @ The RHS entries in the alias table should begin with a single "/" followed by
         2437  +  @ a path element, and optionally followed by "?" and a list of query parameters.
         2438  +  @ <li><p>
         2439  +  @ Query parameters on the RHS are added to the set of query parameters
         2440  +  @ in the incoming URL.
         2441  +  @ <li><p>
         2442  +  @ If the same query parameter appears in both the incoming URL and on the RHS of the
         2443  +  @ alias, the RHS query parameter value overwrites the value on the incoming URL.
         2444  +  @ <li><p>
         2445  +  @ If a query parameter on the RHS of the alias is of the form "X!" (a name followed
         2446  +  @ by "!") then the X query parameter is removed from the incoming URL if it exists.
         2447  +  @ <li><p>
         2448  +  @ Only a single alias operation occurs.  It is not possible to nest aliases.
         2449  +  @ The RHS entries must be built-in webpage names.
         2450  +  @ <li><p>
         2451  +  @ The alias table is only checked if no built-in webpage matches the incoming URL.
         2452  +  @ Hence, it is not possible to override a built-in webpage using aliases.  This is
         2453  +  @ by design.
         2454  +  @ </ul>
         2455  +  @
         2456  +  @ <p>To delete an entry from the alias table, change its name or value to an
         2457  +  @ empty string and press "Apply Changes".
         2458  +  @
         2459  +  @ <p>To add a new alias, fill in the name and value in the bottom row of the table
         2460  +  @ above and press "Apply Changes".
         2461  +  style_footer();
         2462  +}

Changes to src/shell.c.

  1495   1495       sqlite3_finalize(pStmt);
  1496   1496     }
  1497   1497     sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
  1498   1498   }
  1499   1499   
  1500   1500   
  1501   1501   #ifdef _WIN32
  1502         -__declspec(dllexport)
         1502  +
  1503   1503   #endif
  1504   1504   int sqlite3_shathree_init(
  1505   1505     sqlite3 *db,
  1506   1506     char **pzErrMsg,
  1507   1507     const sqlite3_api_routines *pApi
  1508   1508   ){
  1509   1509     int rc = SQLITE_OK;
................................................................................
  1607   1607     }
  1608   1608     fclose(out);
  1609   1609     sqlite3_result_int64(context, rc);
  1610   1610   }
  1611   1611   
  1612   1612   
  1613   1613   #ifdef _WIN32
  1614         -__declspec(dllexport)
         1614  +
  1615   1615   #endif
  1616   1616   int sqlite3_fileio_init(
  1617   1617     sqlite3 *db, 
  1618   1618     char **pzErrMsg, 
  1619   1619     const sqlite3_api_routines *pApi
  1620   1620   ){
  1621   1621     int rc = SQLITE_OK;
................................................................................
  2135   2135   #ifndef SQLITE_OMIT_VIRTUALTABLE
  2136   2136     rc = sqlite3_create_module(db, "completion", &completionModule, 0);
  2137   2137   #endif
  2138   2138     return rc;
  2139   2139   }
  2140   2140   
  2141   2141   #ifdef _WIN32
  2142         -__declspec(dllexport)
         2142  +
  2143   2143   #endif
  2144   2144   int sqlite3_completion_init(
  2145   2145     sqlite3 *db, 
  2146   2146     char **pzErrMsg, 
  2147   2147     const sqlite3_api_routines *pApi
  2148   2148   ){
  2149   2149     int rc = SQLITE_OK;
................................................................................
  2227   2227     OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
  2228   2228   #endif
  2229   2229   };
  2230   2230   
  2231   2231   /*
  2232   2232   ** These are the allowed shellFlgs values
  2233   2233   */
  2234         -#define SHFLG_Scratch        0x00000001 /* The --scratch option is used */
  2235         -#define SHFLG_Pagecache      0x00000002 /* The --pagecache option is used */
  2236         -#define SHFLG_Lookaside      0x00000004 /* Lookaside memory is used */
  2237         -#define SHFLG_Backslash      0x00000008 /* The --backslash option is used */
  2238         -#define SHFLG_PreserveRowid  0x00000010 /* .dump preserves rowid values */
  2239         -#define SHFLG_Newlines       0x00000020 /* .dump --newline flag */
  2240         -#define SHFLG_CountChanges   0x00000040 /* .changes setting */
  2241         -#define SHFLG_Echo           0x00000080 /* .echo or --echo setting */
         2234  +#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
         2235  +#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
         2236  +#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
         2237  +#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
         2238  +#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
         2239  +#define SHFLG_CountChanges   0x00000020 /* .changes setting */
         2240  +#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
  2242   2241   
  2243   2242   /*
  2244   2243   ** Macros for testing and setting shellFlgs
  2245   2244   */
  2246   2245   #define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
  2247   2246   #define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
  2248   2247   #define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
................................................................................
  2655   2654     char **azArg,    /* Text of each result column */
  2656   2655     char **azCol,    /* Column names */
  2657   2656     int *aiType      /* Column types */
  2658   2657   ){
  2659   2658     int i;
  2660   2659     ShellState *p = (ShellState*)pArg;
  2661   2660   
         2661  +  if( azArg==0 ) return 0;
  2662   2662     switch( p->cMode ){
  2663   2663       case MODE_Line: {
  2664   2664         int w = 5;
  2665   2665         if( azArg==0 ) break;
  2666   2666         for(i=0; i<nArg; i++){
  2667   2667           int len = strlen30(azCol[i] ? azCol[i] : "");
  2668   2668           if( len>w ) w = len;
................................................................................
  3005   3005   ** This is the callback routine from sqlite3_exec() that appends all
  3006   3006   ** output onto the end of a ShellText object.
  3007   3007   */
  3008   3008   static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
  3009   3009     ShellText *p = (ShellText*)pArg;
  3010   3010     int i;
  3011   3011     UNUSED_PARAMETER(az);
         3012  +  if( azArg==0 ) return 0;
  3012   3013     if( p->n ) appendText(p, "|", 0);
  3013   3014     for(i=0; i<nArg; i++){
  3014   3015       if( i ) appendText(p, ",", 0);
  3015   3016       if( azArg[i] ) appendText(p, azArg[i], 0);
  3016   3017     }
  3017   3018     return 0;
  3018   3019   }
................................................................................
  3069   3070   /*
  3070   3071   ** Set the destination table field of the ShellState structure to
  3071   3072   ** the name of the table given.  Escape any quote characters in the
  3072   3073   ** table name.
  3073   3074   */
  3074   3075   static void set_table_name(ShellState *p, const char *zName){
  3075   3076     int i, n;
  3076         -  int cQuote;
         3077  +  char cQuote;
  3077   3078     char *z;
  3078   3079   
  3079   3080     if( p->zDestTable ){
  3080   3081       free(p->zDestTable);
  3081   3082       p->zDestTable = 0;
  3082   3083     }
  3083   3084     if( zName==0 ) return;
................................................................................
  3251   3252          "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
  3252   3253       if( pArg->shellFlgs & SHFLG_Pagecache ){
  3253   3254         displayStatLine(pArg, "Number of Pcache Pages Used:",
  3254   3255            "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
  3255   3256       }
  3256   3257       displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
  3257   3258          "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
  3258         -    if( pArg->shellFlgs & SHFLG_Scratch ){
  3259         -      displayStatLine(pArg, "Number of Scratch Allocations Used:",
  3260         -         "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset);
  3261         -    }
  3262         -    displayStatLine(pArg, "Number of Scratch Overflow Bytes:",
  3263         -       "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset);
  3264   3259       displayStatLine(pArg, "Largest Allocation:",
  3265   3260          "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
  3266   3261       displayStatLine(pArg, "Largest Pcache Allocation:",
  3267   3262          "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
  3268         -    displayStatLine(pArg, "Largest Scratch Allocation:",
  3269         -       "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset);
  3270   3263   #ifdef YYTRACKMAXSTACKDEPTH
  3271   3264       displayStatLine(pArg, "Deepest Parser Stack:",
  3272   3265          "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
  3273   3266   #endif
  3274   3267     }
  3275   3268   
  3276   3269     if( pArg && pArg->out && db ){
................................................................................
  3886   3879     int rc;
  3887   3880     const char *zTable;
  3888   3881     const char *zType;
  3889   3882     const char *zSql;
  3890   3883     ShellState *p = (ShellState *)pArg;
  3891   3884   
  3892   3885     UNUSED_PARAMETER(azNotUsed);
  3893         -  if( nArg!=3 ) return 1;
         3886  +  if( nArg!=3 || azArg==0 ) return 0;
  3894   3887     zTable = azArg[0];
  3895   3888     zType = azArg[1];
  3896   3889     zSql = azArg[2];
  3897   3890   
  3898   3891     if( strcmp(zTable, "sqlite_sequence")==0 ){
  3899   3892       raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  3900   3893     }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
................................................................................
  7283   7276         { "benign_malloc_hooks",   SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS    },
  7284   7277         { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
  7285   7278         { "assert",                SQLITE_TESTCTRL_ASSERT                 },
  7286   7279         { "always",                SQLITE_TESTCTRL_ALWAYS                 },
  7287   7280         { "reserve",               SQLITE_TESTCTRL_RESERVE                },
  7288   7281         { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
  7289   7282         { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
  7290         -      { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
  7291   7283         { "byteorder",             SQLITE_TESTCTRL_BYTEORDER              },
  7292   7284         { "never_corrupt",         SQLITE_TESTCTRL_NEVER_CORRUPT          },
  7293   7285         { "imposter",              SQLITE_TESTCTRL_IMPOSTER               },
  7294   7286       };
  7295   7287       int testctrl = -1;
  7296   7288       int rc2 = 0;
  7297   7289       int i, n2;
................................................................................
  7396   7388               raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
  7397   7389             }
  7398   7390             break;
  7399   7391   
  7400   7392           case SQLITE_TESTCTRL_BITVEC_TEST:
  7401   7393           case SQLITE_TESTCTRL_FAULT_INSTALL:
  7402   7394           case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
  7403         -        case SQLITE_TESTCTRL_SCRATCHMALLOC:
  7404   7395           default:
  7405   7396             utf8_printf(stderr,
  7406   7397                         "Error: CLI support for testctrl %s not implemented\n",
  7407   7398                         azArg[1]);
  7408   7399             break;
  7409   7400         }
  7410   7401       }
................................................................................
  7916   7907   #ifdef SQLITE_ENABLE_MULTIPLEX
  7917   7908     "   -multiplex           enable the multiplexor VFS\n"
  7918   7909   #endif
  7919   7910     "   -newline SEP         set output row separator. Default: '\\n'\n"
  7920   7911     "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
  7921   7912     "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  7922   7913     "   -quote               set output mode to 'quote'\n"
  7923         -  "   -scratch SIZE N      use N slots of SZ bytes each for scratch memory\n"
  7924   7914     "   -separator SEP       set output column separator. Default: '|'\n"
  7925   7915     "   -stats               print memory stats before each finalize\n"
  7926   7916     "   -version             show SQLite version\n"
  7927   7917     "   -vfs NAME            use NAME as the default VFS\n"
  7928   7918   #ifdef SQLITE_ENABLE_VFSTRACE
  7929   7919     "   -vfstrace            enable tracing of all VFS calls\n"
  7930   7920   #endif
................................................................................
  8019   8009   
  8020   8010     setBinaryMode(stdin, 0);
  8021   8011     setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
  8022   8012     stdin_is_interactive = isatty(0);
  8023   8013     stdout_is_console = isatty(1);
  8024   8014   
  8025   8015   #if USE_SYSTEM_SQLITE+0!=1
  8026         -  if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
         8016  +  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
  8027   8017       utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
  8028   8018               sqlite3_sourceid(), SQLITE_SOURCE_ID);
  8029   8019       exit(1);
  8030   8020     }
  8031   8021   #endif
  8032   8022     main_init(&data);
  8033   8023   #if !SQLITE_SHELL_IS_UTF8
................................................................................
  8114   8104         zSize = cmdline_option_value(argc, argv, ++i);
  8115   8105         szHeap = integerValue(zSize);
  8116   8106         if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
  8117   8107         sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
  8118   8108   #else
  8119   8109         (void)cmdline_option_value(argc, argv, ++i);
  8120   8110   #endif
  8121         -    }else if( strcmp(z,"-scratch")==0 ){
  8122         -      int n, sz;
  8123         -      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
  8124         -      if( sz>400000 ) sz = 400000;
  8125         -      if( sz<2500 ) sz = 2500;
  8126         -      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
  8127         -      if( n>10 ) n = 10;
  8128         -      if( n<1 ) n = 1;
  8129         -      sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
  8130         -      data.shellFlgs |= SHFLG_Scratch;
  8131   8111       }else if( strcmp(z,"-pagecache")==0 ){
  8132   8112         int n, sz;
  8133   8113         sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
  8134   8114         if( sz>70000 ) sz = 70000;
  8135   8115         if( sz<0 ) sz = 0;
  8136   8116         n = (int)integerValue(cmdline_option_value(argc,argv,++i));
  8137   8117         sqlite3_config(SQLITE_CONFIG_PAGECACHE,
................................................................................
  8267   8247         return 0;
  8268   8248       }else if( strcmp(z,"-interactive")==0 ){
  8269   8249         stdin_is_interactive = 1;
  8270   8250       }else if( strcmp(z,"-batch")==0 ){
  8271   8251         stdin_is_interactive = 0;
  8272   8252       }else if( strcmp(z,"-heap")==0 ){
  8273   8253         i++;
  8274         -    }else if( strcmp(z,"-scratch")==0 ){
  8275         -      i+=2;
  8276   8254       }else if( strcmp(z,"-pagecache")==0 ){
  8277   8255         i+=2;
  8278   8256       }else if( strcmp(z,"-lookaside")==0 ){
  8279   8257         i+=2;
  8280   8258       }else if( strcmp(z,"-mmap")==0 ){
  8281   8259         i++;
  8282   8260       }else if( strcmp(z,"-vfs")==0 ){
................................................................................
  8371   8349   #if HAVE_READLINE || HAVE_EDITLINE
  8372   8350         rl_attempted_completion_function = readline_completion;
  8373   8351   #elif HAVE_LINENOISE
  8374   8352         linenoiseSetCompletionCallback(linenoise_completion);
  8375   8353   #endif
  8376   8354         rc = process_input(&data, 0);
  8377   8355         if( zHistory ){
  8378         -        shell_stifle_history(100);
         8356  +        shell_stifle_history(2000);
  8379   8357           shell_write_history(zHistory);
  8380   8358           free(zHistory);
  8381   8359         }
  8382   8360       }else{
  8383   8361         rc = process_input(&data, stdin);
  8384   8362       }
  8385   8363     }
................................................................................
  8392   8370     find_home_dir(1);
  8393   8371   #if !SQLITE_SHELL_IS_UTF8
  8394   8372     for(i=0; i<argc; i++) sqlite3_free(argv[i]);
  8395   8373     sqlite3_free(argv);
  8396   8374   #endif
  8397   8375     return rc;
  8398   8376   }
  8399         -

Changes to src/shun.c.

   323    323     }else{
   324    324       style_submenu_element("All", "rcvfromlist?all=1");
   325    325     }
   326    326     if( ofst>0 ){
   327    327       style_submenu_element("Newer", "rcvfromlist?ofst=%d",
   328    328                              ofst>perScreen ? ofst-perScreen : 0);
   329    329     }
          330  +  style_submenu_element("Artifacts", "bloblist");
          331  +  style_submenu_element("Top-250", "bigbloblist");
   330    332     db_multi_exec(
   331    333       "CREATE TEMP TABLE rcvidUsed(x INTEGER PRIMARY KEY);"
   332    334       "CREATE TEMP TABLE rcvidSha1(x INTEGER PRIMARY KEY);"
   333    335       "CREATE TEMP TABLE rcvidSha3(x INTEGER PRIMARY KEY);"
   334    336       "INSERT OR IGNORE INTO rcvidUsed(x) SELECT rcvid FROM blob;"
   335    337       "INSERT OR IGNORE INTO rcvidSha1(x)"
   336    338       "   SELECT rcvid FROM blob WHERE length(uuid)==40;"

Changes to src/sqlite3.c.

     1      1   /******************************************************************************
     2      2   ** This file is an amalgamation of many separate C source files from SQLite
     3         -** version 3.20.0.  By combining all the individual C code files into this
            3  +** version 3.21.0.  By combining all the individual C code files into this
     4      4   ** single large file, the entire code can be compiled as a single translation
     5      5   ** unit.  This allows many compilers to do optimizations that would not be
     6      6   ** possible if the files were compiled separately.  Performance improvements
     7      7   ** of 5% or more are commonly seen when SQLite is compiled as a single
     8      8   ** translation unit.
     9      9   **
    10     10   ** This file is all you need to compile SQLite.  To use SQLite in other
................................................................................
   204    204     "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
   205    205   #endif
   206    206   #if SQLITE_ENABLE_API_ARMOR
   207    207     "ENABLE_API_ARMOR",
   208    208   #endif
   209    209   #if SQLITE_ENABLE_ATOMIC_WRITE
   210    210     "ENABLE_ATOMIC_WRITE",
          211  +#endif
          212  +#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
          213  +  "ENABLE_BATCH_ATOMIC_WRITE",
   211    214   #endif
   212    215   #if SQLITE_ENABLE_CEROD
   213    216     "ENABLE_CEROD",
   214    217   #endif
   215    218   #if SQLITE_ENABLE_COLUMN_METADATA
   216    219     "ENABLE_COLUMN_METADATA",
   217    220   #endif
................................................................................
   823    826   ** Make sure the Tcl calling convention macro is defined.  This macro is
   824    827   ** only used by test code and Tcl integration code.
   825    828   */
   826    829   #ifndef SQLITE_TCLAPI
   827    830   #  define SQLITE_TCLAPI
   828    831   #endif
   829    832   
   830         -/*
   831         -** Make sure that rand_s() is available on Windows systems with MSVC 2005
   832         -** or higher.
   833         -*/
   834         -#if defined(_MSC_VER) && _MSC_VER>=1400
   835         -#  define _CRT_RAND_S
   836         -#endif
   837         -
   838    833   /*
   839    834   ** Include the header file used to customize the compiler options for MSVC.
   840    835   ** This should be done first so that it can successfully prevent spurious
   841    836   ** compiler warnings due to subsequent content in this file and other files
   842    837   ** that are included by this file.
   843    838   */
   844    839   /************** Include msvc.h in the middle of sqliteInt.h ******************/
................................................................................
  1140   1135   ** Since [version 3.6.18] ([dateof:3.6.18]), 
  1141   1136   ** SQLite source code has been stored in the
  1142   1137   ** <a href="http://www.fossil-scm.org/">Fossil configuration management
  1143   1138   ** system</a>.  ^The SQLITE_SOURCE_ID macro evaluates to
  1144   1139   ** a string which identifies a particular check-in of SQLite
  1145   1140   ** within its configuration management system.  ^The SQLITE_SOURCE_ID
  1146   1141   ** string contains the date and time of the check-in (UTC) and a SHA1
  1147         -** or SHA3-256 hash of the entire source tree.
         1142  +** or SHA3-256 hash of the entire source tree.  If the source code has
         1143  +** been edited in any way since it was last checked in, then the last
         1144  +** four hexadecimal digits of the hash may be modified.
  1148   1145   **
  1149   1146   ** See also: [sqlite3_libversion()],
  1150   1147   ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
  1151   1148   ** [sqlite_version()] and [sqlite_source_id()].
  1152   1149   */
  1153         -#define SQLITE_VERSION        "3.20.0"
  1154         -#define SQLITE_VERSION_NUMBER 3020000
  1155         -#define SQLITE_SOURCE_ID      "2017-07-15 13:49:56 47cf83a0682b7b3219cf255457f5fbe05f3c1f46be42f6bbab33b78a57a252f6"
         1150  +#define SQLITE_VERSION        "3.21.0"
         1151  +#define SQLITE_VERSION_NUMBER 3021000
         1152  +#define SQLITE_SOURCE_ID      "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bf807a"
  1156   1153   
  1157   1154   /*
  1158   1155   ** CAPI3REF: Run-Time Library Version Numbers
  1159   1156   ** KEYWORDS: sqlite3_version sqlite3_sourceid
  1160   1157   **
  1161   1158   ** These interfaces provide the same information as the [SQLITE_VERSION],
  1162   1159   ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
  1164   1161   ** programmers might include assert() statements in their application to
  1165   1162   ** verify that values returned by these interfaces match the macros in
  1166   1163   ** the header, and thus ensure that the application is
  1167   1164   ** compiled with matching library and header files.
  1168   1165   **
  1169   1166   ** <blockquote><pre>
  1170   1167   ** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
  1171         -** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
         1168  +** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
  1172   1169   ** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
  1173   1170   ** </pre></blockquote>)^
  1174   1171   **
  1175   1172   ** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
  1176   1173   ** macro.  ^The sqlite3_libversion() function returns a pointer to the
  1177   1174   ** to the sqlite3_version[] string constant.  The sqlite3_libversion()
  1178   1175   ** function is provided for use in DLLs since DLL users usually do not have
  1179   1176   ** direct access to string constants within the DLL.  ^The
  1180   1177   ** sqlite3_libversion_number() function returns an integer equal to
  1181         -** [SQLITE_VERSION_NUMBER].  ^The sqlite3_sourceid() function returns 
         1178  +** [SQLITE_VERSION_NUMBER].  ^(The sqlite3_sourceid() function returns 
  1182   1179   ** a pointer to a string constant whose value is the same as the 
  1183         -** [SQLITE_SOURCE_ID] C preprocessor macro.
         1180  +** [SQLITE_SOURCE_ID] C preprocessor macro.  Except if SQLite is built
         1181  +** using an edited copy of [the amalgamation], then the last four characters
         1182  +** of the hash might be different from [SQLITE_SOURCE_ID].)^
  1184   1183   **
  1185   1184   ** See also: [sqlite_version()] and [sqlite_source_id()].
  1186   1185   */
  1187   1186   SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
  1188   1187   SQLITE_API const char *sqlite3_libversion(void);
  1189   1188   SQLITE_API const char *sqlite3_sourceid(void);
  1190   1189   SQLITE_API int sqlite3_libversion_number(void);
................................................................................
  1457   1456   #define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite3_interrupt()*/
  1458   1457   #define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
  1459   1458   #define SQLITE_CORRUPT     11   /* The database disk image is malformed */
  1460   1459   #define SQLITE_NOTFOUND    12   /* Unknown opcode in sqlite3_file_control() */
  1461   1460   #define SQLITE_FULL        13   /* Insertion failed because database is full */
  1462   1461   #define SQLITE_CANTOPEN    14   /* Unable to open the database file */
  1463   1462   #define SQLITE_PROTOCOL    15   /* Database lock protocol error */
  1464         -#define SQLITE_EMPTY       16   /* Not used */
         1463  +#define SQLITE_EMPTY       16   /* Internal use only */
  1465   1464   #define SQLITE_SCHEMA      17   /* The database schema changed */
  1466   1465   #define SQLITE_TOOBIG      18   /* String or BLOB exceeds size limit */
  1467   1466   #define SQLITE_CONSTRAINT  19   /* Abort due to constraint violation */
  1468   1467   #define SQLITE_MISMATCH    20   /* Data type mismatch */
  1469   1468   #define SQLITE_MISUSE      21   /* Library used incorrectly */
  1470   1469   #define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
  1471   1470   #define SQLITE_AUTH        23   /* Authorization denied */
................................................................................
  1519   1518   #define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
  1520   1519   #define SQLITE_IOERR_DELETE_NOENT      (SQLITE_IOERR | (23<<8))
  1521   1520   #define SQLITE_IOERR_MMAP              (SQLITE_IOERR | (24<<8))
  1522   1521   #define SQLITE_IOERR_GETTEMPPATH       (SQLITE_IOERR | (25<<8))
  1523   1522   #define SQLITE_IOERR_CONVPATH          (SQLITE_IOERR | (26<<8))
  1524   1523   #define SQLITE_IOERR_VNODE             (SQLITE_IOERR | (27<<8))
  1525   1524   #define SQLITE_IOERR_AUTH              (SQLITE_IOERR | (28<<8))
         1525  +#define SQLITE_IOERR_BEGIN_ATOMIC      (SQLITE_IOERR | (29<<8))
         1526  +#define SQLITE_IOERR_COMMIT_ATOMIC     (SQLITE_IOERR | (30<<8))
         1527  +#define SQLITE_IOERR_ROLLBACK_ATOMIC   (SQLITE_IOERR | (31<<8))
  1526   1528   #define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
  1527   1529   #define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
  1528   1530   #define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
  1529   1531   #define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
  1530   1532   #define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
  1531   1533   #define SQLITE_CANTOPEN_FULLPATH       (SQLITE_CANTOPEN | (3<<8))
  1532   1534   #define SQLITE_CANTOPEN_CONVPATH       (SQLITE_CANTOPEN | (4<<8))
................................................................................
  1605   1607   ** file that were written at the application level might have changed
  1606   1608   ** and that adjacent bytes, even bytes within the same sector are
  1607   1609   ** guaranteed to be unchanged.  The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
  1608   1610   ** flag indicates that a file cannot be deleted when open.  The
  1609   1611   ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
  1610   1612   ** read-only media and cannot be changed even by processes with
  1611   1613   ** elevated privileges.
         1614  +**
         1615  +** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
         1616  +** filesystem supports doing multiple write operations atomically when those
         1617  +** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
         1618  +** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
  1612   1619   */
  1613   1620   #define SQLITE_IOCAP_ATOMIC                 0x00000001
  1614   1621   #define SQLITE_IOCAP_ATOMIC512              0x00000002
  1615   1622   #define SQLITE_IOCAP_ATOMIC1K               0x00000004
  1616   1623   #define SQLITE_IOCAP_ATOMIC2K               0x00000008
  1617   1624   #define SQLITE_IOCAP_ATOMIC4K               0x00000010
  1618   1625   #define SQLITE_IOCAP_ATOMIC8K               0x00000020
................................................................................
  1620   1627   #define SQLITE_IOCAP_ATOMIC32K              0x00000080
  1621   1628   #define SQLITE_IOCAP_ATOMIC64K              0x00000100
  1622   1629   #define SQLITE_IOCAP_SAFE_APPEND            0x00000200
  1623   1630   #define SQLITE_IOCAP_SEQUENTIAL             0x00000400
  1624   1631   #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN  0x00000800
  1625   1632   #define SQLITE_IOCAP_POWERSAFE_OVERWRITE    0x00001000
  1626   1633   #define SQLITE_IOCAP_IMMUTABLE              0x00002000
         1634  +#define SQLITE_IOCAP_BATCH_ATOMIC           0x00004000
  1627   1635   
  1628   1636   /*
  1629   1637   ** CAPI3REF: File Locking Levels
  1630   1638   **
  1631   1639   ** SQLite uses one of these integer values as the second
  1632   1640   ** argument to calls it makes to the xLock() and xUnlock() methods
  1633   1641   ** of an [sqlite3_io_methods] object.
................................................................................
  1754   1762   ** <li> [SQLITE_IOCAP_ATOMIC32K]
  1755   1763   ** <li> [SQLITE_IOCAP_ATOMIC64K]
  1756   1764   ** <li> [SQLITE_IOCAP_SAFE_APPEND]
  1757   1765   ** <li> [SQLITE_IOCAP_SEQUENTIAL]
  1758   1766   ** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
  1759   1767   ** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
  1760   1768   ** <li> [SQLITE_IOCAP_IMMUTABLE]
         1769  +** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
  1761   1770   ** </ul>
  1762   1771   **
  1763   1772   ** The SQLITE_IOCAP_ATOMIC property means that all writes of
  1764   1773   ** any size are atomic.  The SQLITE_IOCAP_ATOMICnnn values
  1765   1774   ** mean that writes of blocks that are nnn bytes in size and
  1766   1775   ** are aligned to an address which is an integer multiple of
  1767   1776   ** nnn are atomic.  The SQLITE_IOCAP_SAFE_APPEND value means
................................................................................
  2037   2046   ** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
  2038   2047   ** VFS should return SQLITE_NOTFOUND for this opcode.
  2039   2048   **
  2040   2049   ** <li>[[SQLITE_FCNTL_RBU]]
  2041   2050   ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
  2042   2051   ** the RBU extension only.  All other VFS should return SQLITE_NOTFOUND for
  2043   2052   ** this opcode.  
         2053  +**
         2054  +** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
         2055  +** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
         2056  +** the file descriptor is placed in "batch write mode", which
         2057  +** means all subsequent write operations will be deferred and done
         2058  +** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].  Systems
         2059  +** that do not support batch atomic writes will return SQLITE_NOTFOUND.
         2060  +** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
         2061  +** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
         2062  +** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
         2063  +** no VFS interface calls on the same [sqlite3_file] file descriptor
         2064  +** except for calls to the xWrite method and the xFileControl method
         2065  +** with [SQLITE_FCNTL_SIZE_HINT].
         2066  +**
         2067  +** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
         2068  +** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
         2069  +** operations since the previous successful call to 
         2070  +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
         2071  +** This file control returns [SQLITE_OK] if and only if the writes were
         2072  +** all performed successfully and have been committed to persistent storage.
         2073  +** ^Regardless of whether or not it is successful, this file control takes
         2074  +** the file descriptor out of batch write mode so that all subsequent
         2075  +** write operations are independent.
         2076  +** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
         2077  +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
         2078  +**
         2079  +** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
         2080  +** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
         2081  +** operations since the previous successful call to 
         2082  +** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
         2083  +** ^This file control takes the file descriptor out of batch write mode
         2084  +** so that all subsequent write operations are independent.
         2085  +** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
         2086  +** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
  2044   2087   ** </ul>
  2045   2088   */
  2046   2089   #define SQLITE_FCNTL_LOCKSTATE               1
  2047   2090   #define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
  2048   2091   #define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
  2049   2092   #define SQLITE_FCNTL_LAST_ERRNO              4
  2050   2093   #define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
  2068   2111   #define SQLITE_FCNTL_WAL_BLOCK              24
  2069   2112   #define SQLITE_FCNTL_ZIPVFS                 25
  2070   2113   #define SQLITE_FCNTL_RBU                    26
  2071   2114   #define SQLITE_FCNTL_VFS_POINTER            27
  2072   2115   #define SQLITE_FCNTL_JOURNAL_POINTER        28
  2073   2116   #define SQLITE_FCNTL_WIN32_GET_HANDLE       29
  2074   2117   #define SQLITE_FCNTL_PDB                    30
         2118  +#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE     31
         2119  +#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE    32
         2120  +#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
  2075   2121   
  2076   2122   /* deprecated names */
  2077   2123   #define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
  2078   2124   #define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
  2079   2125   #define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO
  2080   2126   
  2081   2127   
................................................................................
  2637   2683   ** <dd> ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which
  2638   2684   ** is a pointer to an instance of the [sqlite3_mem_methods] structure.
  2639   2685   ** The [sqlite3_mem_methods]
  2640   2686   ** structure is filled with the currently defined memory allocation routines.)^
  2641   2687   ** This option can be used to overload the default memory allocation
  2642   2688   ** routines with a wrapper that simulations memory allocation failure or
  2643   2689   ** tracks memory usage, for example. </dd>
         2690  +**
         2691  +** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
         2692  +** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
         2693  +** type int, interpreted as a boolean, which if true provides a hint to
         2694  +** SQLite that it should avoid large memory allocations if possible.
         2695  +** SQLite will run faster if it is free to make large memory allocations,
         2696  +** but some application might prefer to run slower in exchange for
         2697  +** guarantees about memory fragmentation that are possible if large
         2698  +** allocations are avoided.  This hint is normally off.
         2699  +** </dd>
  2644   2700   **
  2645   2701   ** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
  2646   2702   ** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
  2647   2703   ** interpreted as a boolean, which enables or disables the collection of
  2648   2704   ** memory allocation statistics. ^(When memory allocation statistics are
  2649   2705   ** disabled, the following SQLite interfaces become non-operational:
  2650   2706   **   <ul>
................................................................................
  2655   2711   **   </ul>)^
  2656   2712   ** ^Memory allocation statistics are enabled by default unless SQLite is
  2657   2713   ** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
  2658   2714   ** allocation statistics are disabled by default.
  2659   2715   ** </dd>
  2660   2716   **
  2661   2717   ** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
  2662         -** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer
  2663         -** that SQLite can use for scratch memory.  ^(There are three arguments
  2664         -** to SQLITE_CONFIG_SCRATCH:  A pointer an 8-byte
  2665         -** aligned memory buffer from which the scratch allocations will be
  2666         -** drawn, the size of each scratch allocation (sz),
  2667         -** and the maximum number of scratch allocations (N).)^
  2668         -** The first argument must be a pointer to an 8-byte aligned buffer
  2669         -** of at least sz*N bytes of memory.
  2670         -** ^SQLite will not use more than one scratch buffers per thread.
  2671         -** ^SQLite will never request a scratch buffer that is more than 6
  2672         -** times the database page size.
  2673         -** ^If SQLite needs needs additional
  2674         -** scratch memory beyond what is provided by this configuration option, then 
  2675         -** [sqlite3_malloc()] will be used to obtain the memory needed.<p>
  2676         -** ^When the application provides any amount of scratch memory using
  2677         -** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large
  2678         -** [sqlite3_malloc|heap allocations].
  2679         -** This can help [Robson proof|prevent memory allocation failures] due to heap
  2680         -** fragmentation in low-memory embedded systems.
         2718  +** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
  2681   2719   ** </dd>
  2682   2720   **
  2683   2721   ** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
  2684   2722   ** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
  2685   2723   ** that SQLite can use for the database page cache with the default page
  2686   2724   ** cache implementation.  
  2687   2725   ** This configuration option is a no-op if an application-define page
................................................................................
  2709   2747   ** page cache memory is needed beyond what is provided by the initial
  2710   2748   ** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
  2711   2749   ** additional cache line. </dd>
  2712   2750   **
  2713   2751   ** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
  2714   2752   ** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer 
  2715   2753   ** that SQLite will use for all of its dynamic memory allocation needs
  2716         -** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and
  2717         -** [SQLITE_CONFIG_PAGECACHE].
         2754  +** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
  2718   2755   ** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
  2719   2756   ** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
  2720   2757   ** [SQLITE_ERROR] if invoked otherwise.
  2721   2758   ** ^There are three arguments to SQLITE_CONFIG_HEAP:
  2722   2759   ** An 8-byte aligned pointer to the memory,
  2723   2760   ** the number of bytes in the memory buffer, and the minimum allocation size.
  2724   2761   ** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
................................................................................
  2903   2940   ** </dl>
  2904   2941   */
  2905   2942   #define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
  2906   2943   #define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
  2907   2944   #define SQLITE_CONFIG_SERIALIZED    3  /* nil */
  2908   2945   #define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
  2909   2946   #define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
  2910         -#define SQLITE_CONFIG_SCRATCH       6  /* void*, int sz, int N */
         2947  +#define SQLITE_CONFIG_SCRATCH       6  /* No longer used */
  2911   2948   #define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
  2912   2949   #define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
  2913   2950   #define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
  2914   2951   #define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
  2915   2952   #define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
  2916   2953   /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ 
  2917   2954   #define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
................................................................................
  2924   2961   #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
  2925   2962   #define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
  2926   2963   #define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
  2927   2964   #define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
  2928   2965   #define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
  2929   2966   #define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */
  2930   2967   #define SQLITE_CONFIG_STMTJRNL_SPILL      26  /* int nByte */
         2968  +#define SQLITE_CONFIG_SMALL_MALLOC        27  /* boolean */
  2931   2969   
  2932   2970   /*
  2933   2971   ** CAPI3REF: Database Connection Configuration Options
  2934   2972   **
  2935   2973   ** These constants are the available integer configuration options that
  2936   2974   ** can be passed as the second argument to the [sqlite3_db_config()] interface.
  2937   2975   **
................................................................................
  4124   4162   ** automatically deleted as soon as the database connection is closed.
  4125   4163   **
  4126   4164   ** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
  4127   4165   **
  4128   4166   ** ^If [URI filename] interpretation is enabled, and the filename argument
  4129   4167   ** begins with "file:", then the filename is interpreted as a URI. ^URI
  4130   4168   ** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
  4131         -** set in the fourth argument to sqlite3_open_v2(), or if it has
         4169  +** set in the third argument to sqlite3_open_v2(), or if it has
  4132   4170   ** been enabled globally using the [SQLITE_CONFIG_URI] option with the
  4133   4171   ** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
  4134         -** As of SQLite version 3.7.7, URI filename interpretation is turned off
         4172  +** URI filename interpretation is turned off
  4135   4173   ** by default, but future releases of SQLite might enable URI filename
  4136   4174   ** interpretation by default.  See "[URI filenames]" for additional
  4137   4175   ** information.
  4138   4176   **
  4139   4177   ** URI filenames are parsed according to RFC 3986. ^If the URI contains an
  4140   4178   ** authority, then it must be either an empty string or the string 
  4141   4179   ** "localhost". ^If the authority is not an empty string or "localhost", an 
................................................................................
  4670   4708     sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
  4671   4709     const void **pzTail     /* OUT: Pointer to unused portion of zSql */
  4672   4710   );
  4673   4711   SQLITE_API int sqlite3_prepare16_v3(
  4674   4712     sqlite3 *db,            /* Database handle */
  4675   4713     const void *zSql,       /* SQL statement, UTF-16 encoded */
  4676   4714     int nByte,              /* Maximum length of zSql in bytes. */
  4677         -  unsigned int prepFalgs, /* Zero or more SQLITE_PREPARE_ flags */
         4715  +  unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
  4678   4716     sqlite3_stmt **ppStmt,  /* OUT: Statement handle */
  4679   4717     const void **pzTail     /* OUT: Pointer to unused portion of zSql */
  4680   4718   );
  4681   4719   
  4682   4720   /*
  4683   4721   ** CAPI3REF: Retrieving Statement SQL
  4684   4722   ** METHOD: sqlite3_stmt
................................................................................
  4801   4839   ** still make the distinction between protected and unprotected
  4802   4840   ** sqlite3_value objects even when not strictly required.
  4803   4841   **
  4804   4842   ** ^The sqlite3_value objects that are passed as parameters into the
  4805   4843   ** implementation of [application-defined SQL functions] are protected.
  4806   4844   ** ^The sqlite3_value object returned by
  4807   4845   ** [sqlite3_column_value()] is unprotected.
  4808         -** Unprotected sqlite3_value objects may only be used with
  4809         -** [sqlite3_result_value()] and [sqlite3_bind_value()].
         4846  +** Unprotected sqlite3_value objects may only be used as arguments
         4847  +** to [sqlite3_result_value()], [sqlite3_bind_value()], and
         4848  +** [sqlite3_value_dup()].
  4810   4849   ** The [sqlite3_value_blob | sqlite3_value_type()] family of
  4811   4850   ** interfaces require protected sqlite3_value objects.
  4812   4851   */
  4813   4852   typedef struct sqlite3_value sqlite3_value;
  4814   4853   
  4815   4854   /*
  4816   4855   ** CAPI3REF: SQL Function Context Object
................................................................................
  4908   4947   ** is filled with zeroes.  ^A zeroblob uses a fixed amount of memory
  4909   4948   ** (just an integer to hold its size) while it is being processed.
  4910   4949   ** Zeroblobs are intended to serve as placeholders for BLOBs whose
  4911   4950   ** content is later written using
  4912   4951   ** [sqlite3_blob_open | incremental BLOB I/O] routines.
  4913   4952   ** ^A negative value for the zeroblob results in a zero-length BLOB.
  4914   4953   **
  4915         -** ^The sqlite3_bind_pointer(S,I,P) routine causes the I-th parameter in
         4954  +** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
  4916   4955   ** [prepared statement] S to have an SQL value of NULL, but to also be
  4917         -** associated with the pointer P.
  4918         -** ^The sqlite3_bind_pointer() routine can be used to pass
  4919         -** host-language pointers into [application-defined SQL functions].
  4920         -** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
  4921         -** to be an ordinary SQL NULL value to everything other than
  4922         -** [sqlite3_value_pointer()].
         4956  +** associated with the pointer P of type T.  ^D is either a NULL pointer or
         4957  +** a pointer to a destructor function for P. ^SQLite will invoke the
         4958  +** destructor D with a single argument of P when it is finished using
         4959  +** P.  The T parameter should be a static string, preferably a string
         4960  +** literal. The sqlite3_bind_pointer() routine is part of the
         4961  +** [pointer passing interface] added for SQLite 3.20.0.
  4923   4962   **
  4924   4963   ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
  4925   4964   ** for the [prepared statement] or with a prepared statement for which
  4926   4965   ** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
  4927   4966   ** then the call will return [SQLITE_MISUSE].  If any sqlite3_bind_()
  4928   4967   ** routine is passed a [prepared statement] that has been finalized, the
  4929   4968   ** result is undefined and probably harmful.
................................................................................
  4950   4989   SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
  4951   4990   SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
  4952   4991   SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
  4953   4992   SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
  4954   4993   SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
  4955   4994                            void(*)(void*), unsigned char encoding);
  4956   4995   SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
  4957         -SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*);
         4996  +SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
  4958   4997   SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
  4959   4998   SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
  4960   4999   
  4961   5000   /*
  4962   5001   ** CAPI3REF: Number Of SQL Parameters
  4963   5002   ** METHOD: sqlite3_stmt
  4964   5003   **
................................................................................
  5783   5822   **
  5784   5823   ** ^The sqlite3_value_text16() interface extracts a UTF-16 string
  5785   5824   ** in the native byte-order of the host machine.  ^The
  5786   5825   ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
  5787   5826   ** extract UTF-16 strings as big-endian and little-endian respectively.
  5788   5827   **
  5789   5828   ** ^If [sqlite3_value] object V was initialized 
  5790         -** using [sqlite3_bind_pointer(S,I,P)] or [sqlite3_result_pointer(C,P)], then
  5791         -** sqlite3_value_pointer(V) will return the pointer P.  Otherwise,
  5792         -** sqlite3_value_pointer(V) returns a NULL.
         5829  +** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
         5830  +** and if X and Y are strings that compare equal according to strcmp(X,Y),
         5831  +** then sqlite3_value_pointer(V,Y) will return the pointer P.  ^Otherwise,
         5832  +** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer() 
         5833  +** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
  5793   5834   **
  5794   5835   ** ^(The sqlite3_value_type(V) interface returns the
  5795   5836   ** [SQLITE_INTEGER | datatype code] for the initial datatype of the
  5796   5837   ** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
  5797   5838   ** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^
  5798   5839   ** Other interfaces might change the datatype for an sqlite3_value object.
  5799   5840   ** For example, if the datatype is initially SQLITE_INTEGER and
................................................................................
  5819   5860   ** These routines must be called from the same thread as
  5820   5861   ** the SQL function that supplied the [sqlite3_value*] parameters.
  5821   5862   */
  5822   5863   SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
  5823   5864   SQLITE_API double sqlite3_value_double(sqlite3_value*);
  5824   5865   SQLITE_API int sqlite3_value_int(sqlite3_value*);
  5825   5866   SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
  5826         -SQLITE_API void *sqlite3_value_pointer(sqlite3_value*);
         5867  +SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*);
  5827   5868   SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
  5828   5869   SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
  5829   5870   SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
  5830   5871   SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
  5831   5872   SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
  5832   5873   SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
  5833   5874   SQLITE_API int sqlite3_value_type(sqlite3_value*);
................................................................................
  6120   6161   ** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
  6121   6162   ** so that the [sqlite3_value] specified in the parameter may change or
  6122   6163   ** be deallocated after sqlite3_result_value() returns without harm.
  6123   6164   ** ^A [protected sqlite3_value] object may always be used where an
  6124   6165   ** [unprotected sqlite3_value] object is required, so either
  6125   6166   ** kind of [sqlite3_value] object can be used with this interface.
  6126   6167   **
  6127         -** ^The sqlite3_result_pointer(C,P) interface sets the result to an
         6168  +** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
  6128   6169   ** SQL NULL value, just like [sqlite3_result_null(C)], except that it
  6129         -** also associates the host-language pointer P with that NULL value such
  6130         -** that the pointer can be retrieved within an
         6170  +** also associates the host-language pointer P or type T with that 
         6171  +** NULL value such that the pointer can be retrieved within an
  6131   6172   ** [application-defined SQL function] using [sqlite3_value_pointer()].
  6132         -** This mechanism can be used to pass non-SQL values between
  6133         -** application-defined functions.
         6173  +** ^If the D parameter is not NULL, then it is a pointer to a destructor
         6174  +** for the P parameter.  ^SQLite invokes D with P as its only argument
         6175  +** when SQLite is finished with P.  The T parameter should be a static
         6176  +** string and preferably a string literal. The sqlite3_result_pointer()
         6177  +** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
  6134   6178   **
  6135   6179   ** If these routines are called from within the different thread
  6136   6180   ** than the one containing the application-defined function that received
  6137   6181   ** the [sqlite3_context] pointer, the results are undefined.
  6138   6182   */
  6139   6183   SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
  6140   6184   SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
................................................................................
  6151   6195   SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
  6152   6196   SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
  6153   6197                              void(*)(void*), unsigned char encoding);
  6154   6198   SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
  6155   6199   SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
  6156   6200   SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
  6157   6201   SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
  6158         -SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*);
         6202  +SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
  6159   6203   SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
  6160   6204   SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
  6161   6205   
  6162   6206   
  6163   6207   /*
  6164   6208   ** CAPI3REF: Setting The Subtype Of An SQL Function
  6165   6209   ** METHOD: sqlite3_context
................................................................................
  7223   7267   ** CAPI3REF: Virtual Table Constraint Operator Codes
  7224   7268   **
  7225   7269   ** These macros defined the allowed values for the
  7226   7270   ** [sqlite3_index_info].aConstraint[].op field.  Each value represents
  7227   7271   ** an operator that is part of a constraint term in the wHERE clause of
  7228   7272   ** a query that uses a [virtual table].
  7229   7273   */
  7230         -#define SQLITE_INDEX_CONSTRAINT_EQ      2
  7231         -#define SQLITE_INDEX_CONSTRAINT_GT      4
  7232         -#define SQLITE_INDEX_CONSTRAINT_LE      8
  7233         -#define SQLITE_INDEX_CONSTRAINT_LT     16
  7234         -#define SQLITE_INDEX_CONSTRAINT_GE     32
  7235         -#define SQLITE_INDEX_CONSTRAINT_MATCH  64
  7236         -#define SQLITE_INDEX_CONSTRAINT_LIKE   65
  7237         -#define SQLITE_INDEX_CONSTRAINT_GLOB   66
  7238         -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
         7274  +#define SQLITE_INDEX_CONSTRAINT_EQ         2
         7275  +#define SQLITE_INDEX_CONSTRAINT_GT         4
         7276  +#define SQLITE_INDEX_CONSTRAINT_LE         8
         7277  +#define SQLITE_INDEX_CONSTRAINT_LT        16
         7278  +#define SQLITE_INDEX_CONSTRAINT_GE        32
         7279  +#define SQLITE_INDEX_CONSTRAINT_MATCH     64
         7280  +#define SQLITE_INDEX_CONSTRAINT_LIKE      65
         7281  +#define SQLITE_INDEX_CONSTRAINT_GLOB      66
         7282  +#define SQLITE_INDEX_CONSTRAINT_REGEXP    67
         7283  +#define SQLITE_INDEX_CONSTRAINT_NE        68
         7284  +#define SQLITE_INDEX_CONSTRAINT_ISNOT     69
         7285  +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
         7286  +#define SQLITE_INDEX_CONSTRAINT_ISNULL    71
         7287  +#define SQLITE_INDEX_CONSTRAINT_IS        72
  7239   7288   
  7240   7289   /*
  7241   7290   ** CAPI3REF: Register A Virtual Table Implementation
  7242   7291   ** METHOD: sqlite3
  7243   7292   **
  7244   7293   ** ^These routines are used to register a new [virtual table module] name.
  7245   7294   ** ^Module names must be registered before
................................................................................
  7983   8032   #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
  7984   8033   #define SQLITE_TESTCTRL_PENDING_BYTE            11
  7985   8034   #define SQLITE_TESTCTRL_ASSERT                  12
  7986   8035   #define SQLITE_TESTCTRL_ALWAYS                  13
  7987   8036   #define SQLITE_TESTCTRL_RESERVE                 14
  7988   8037   #define SQLITE_TESTCTRL_OPTIMIZATIONS           15
  7989   8038   #define SQLITE_TESTCTRL_ISKEYWORD               16
  7990         -#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
         8039  +#define SQLITE_TESTCTRL_SCRATCHMALLOC           17  /* NOT USED */
  7991   8040   #define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
  7992   8041   #define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
  7993   8042   #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD    19
  7994   8043   #define SQLITE_TESTCTRL_NEVER_CORRUPT           20
  7995   8044   #define SQLITE_TESTCTRL_VDBE_COVERAGE           21
  7996   8045   #define SQLITE_TESTCTRL_BYTEORDER               22
  7997   8046   #define SQLITE_TESTCTRL_ISINIT                  23
................................................................................
  8042   8091   ** that can be returned by [sqlite3_status()].
  8043   8092   **
  8044   8093   ** <dl>
  8045   8094   ** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
  8046   8095   ** <dd>This parameter is the current amount of memory checked out
  8047   8096   ** using [sqlite3_malloc()], either directly or indirectly.  The
  8048   8097   ** figure includes calls made to [sqlite3_malloc()] by the application
  8049         -** and internal memory usage by the SQLite library.  Scratch memory
  8050         -** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
         8098  +** and internal memory usage by the SQLite library.  Auxiliary page-cache
  8051   8099   ** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
  8052   8100   ** this parameter.  The amount returned is the sum of the allocation
  8053   8101   ** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
  8054   8102   **
  8055   8103   ** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
  8056   8104   ** <dd>This parameter records the largest memory allocation request
  8057   8105   ** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
................................................................................
  8081   8129   **
  8082   8130   ** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
  8083   8131   ** <dd>This parameter records the largest memory allocation request
  8084   8132   ** handed to [pagecache memory allocator].  Only the value returned in the
  8085   8133   ** *pHighwater parameter to [sqlite3_status()] is of interest.  
  8086   8134   ** The value written into the *pCurrent parameter is undefined.</dd>)^
  8087   8135   **
  8088         -** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
  8089         -** <dd>This parameter returns the number of allocations used out of the
  8090         -** [scratch memory allocator] configured using
  8091         -** [SQLITE_CONFIG_SCRATCH].  The value returned is in allocations, not
  8092         -** in bytes.  Since a single thread may only have one scratch allocation
  8093         -** outstanding at time, this parameter also reports the number of threads
  8094         -** using scratch memory at the same time.</dd>)^
         8136  +** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
         8137  +** <dd>No longer used.</dd>
  8095   8138   **
  8096   8139   ** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
  8097         -** <dd>This parameter returns the number of bytes of scratch memory
  8098         -** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
  8099         -** buffer and where forced to overflow to [sqlite3_malloc()].  The values
  8100         -** returned include overflows because the requested allocation was too
  8101         -** larger (that is, because the requested allocation was larger than the
  8102         -** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
  8103         -** slots were available.
  8104         -** </dd>)^
         8140  +** <dd>No longer used.</dd>
  8105   8141   **
  8106         -** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
  8107         -** <dd>This parameter records the largest memory allocation request
  8108         -** handed to [scratch memory allocator].  Only the value returned in the
  8109         -** *pHighwater parameter to [sqlite3_status()] is of interest.  
  8110         -** The value written into the *pCurrent parameter is undefined.</dd>)^
         8142  +** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
         8143  +** <dd>No longer used.</dd>
  8111   8144   **
  8112   8145   ** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
  8113   8146   ** <dd>The *pHighwater parameter records the deepest parser stack. 
  8114   8147   ** The *pCurrent value is undefined.  The *pHighwater value is only
  8115   8148   ** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
  8116   8149   ** </dl>
  8117   8150   **
  8118   8151   ** New status parameters may be added from time to time.
  8119   8152   */
  8120   8153   #define SQLITE_STATUS_MEMORY_USED          0
  8121   8154   #define SQLITE_STATUS_PAGECACHE_USED       1
  8122   8155   #define SQLITE_STATUS_PAGECACHE_OVERFLOW   2
  8123         -#define SQLITE_STATUS_SCRATCH_USED         3
  8124         -#define SQLITE_STATUS_SCRATCH_OVERFLOW     4
         8156  +#define SQLITE_STATUS_SCRATCH_USED         3  /* NOT USED */
         8157  +#define SQLITE_STATUS_SCRATCH_OVERFLOW     4  /* NOT USED */
  8125   8158   #define SQLITE_STATUS_MALLOC_SIZE          5
  8126   8159   #define SQLITE_STATUS_PARSER_STACK         6
  8127   8160   #define SQLITE_STATUS_PAGECACHE_SIZE       7
  8128         -#define SQLITE_STATUS_SCRATCH_SIZE         8
         8161  +#define SQLITE_STATUS_SCRATCH_SIZE         8  /* NOT USED */
  8129   8162   #define SQLITE_STATUS_MALLOC_COUNT         9
  8130   8163   
  8131   8164   /*
  8132   8165   ** CAPI3REF: Database Connection Status
  8133   8166   ** METHOD: sqlite3
  8134   8167   **
  8135   8168   ** ^This interface is used to retrieve runtime status information 
................................................................................
 12405  12438   #define TK_EXISTS                          20
 12406  12439   #define TK_TEMP                            21
 12407  12440   #define TK_LP                              22
 12408  12441   #define TK_RP                              23
 12409  12442   #define TK_AS                              24
 12410  12443   #define TK_WITHOUT                         25
 12411  12444   #define TK_COMMA                           26
 12412         -#define TK_ID                              27
 12413         -#define TK_ABORT                           28
 12414         -#define TK_ACTION                          29
 12415         -#define TK_AFTER                           30
 12416         -#define TK_ANALYZE                         31
 12417         -#define TK_ASC                             32
 12418         -#define TK_ATTACH                          33
 12419         -#define TK_BEFORE                          34
 12420         -#define TK_BY                              35
 12421         -#define TK_CASCADE                         36
 12422         -#define TK_CAST                            37
 12423         -#define TK_COLUMNKW                        38
 12424         -#define TK_CONFLICT                        39
 12425         -#define TK_DATABASE                        40
 12426         -#define TK_DESC                            41
 12427         -#define TK_DETACH                          42
 12428         -#define TK_EACH                            43
 12429         -#define TK_FAIL                            44
 12430         -#define TK_FOR                             45
 12431         -#define TK_IGNORE                          46
 12432         -#define TK_INITIALLY                       47
 12433         -#define TK_INSTEAD                         48
 12434         -#define TK_LIKE_KW                         49
 12435         -#define TK_MATCH                           50
 12436         -#define TK_NO                              51
 12437         -#define TK_KEY                             52
 12438         -#define TK_OF                              53
 12439         -#define TK_OFFSET                          54
 12440         -#define TK_PRAGMA                          55
 12441         -#define TK_RAISE                           56
 12442         -#define TK_RECURSIVE                       57
 12443         -#define TK_REPLACE                         58
 12444         -#define TK_RESTRICT                        59
 12445         -#define TK_ROW                             60
 12446         -#define TK_TRIGGER                         61
 12447         -#define TK_VACUUM                          62
 12448         -#define TK_VIEW                            63
 12449         -#define TK_VIRTUAL                         64
 12450         -#define TK_WITH                            65
 12451         -#define TK_REINDEX                         66
 12452         -#define TK_RENAME                          67
 12453         -#define TK_CTIME_KW                        68
 12454         -#define TK_ANY                             69
 12455         -#define TK_OR                              70
 12456         -#define TK_AND                             71
 12457         -#define TK_IS                              72
 12458         -#define TK_BETWEEN                         73
 12459         -#define TK_IN                              74
 12460         -#define TK_ISNULL                          75
 12461         -#define TK_NOTNULL                         76
 12462         -#define TK_NE                              77
 12463         -#define TK_EQ                              78
 12464         -#define TK_GT                              79
 12465         -#define TK_LE                              80
 12466         -#define TK_LT                              81
 12467         -#define TK_GE                              82
 12468         -#define TK_ESCAPE                          83
        12445  +#define TK_ABORT                           27
        12446  +#define TK_ACTION                          28
        12447  +#define TK_AFTER                           29
        12448  +#define TK_ANALYZE                         30
        12449  +#define TK_ASC                             31
        12450  +#define TK_ATTACH                          32
        12451  +#define TK_BEFORE                          33
        12452  +#define TK_BY                              34
        12453  +#define TK_CASCADE                         35
        12454  +#define TK_CAST                            36
        12455  +#define TK_CONFLICT                        37
        12456  +#define TK_DATABASE                        38
        12457  +#define TK_DESC                            39
        12458  +#define TK_DETACH                          40
        12459  +#define TK_EACH                            41
        12460  +#define TK_FAIL                            42
        12461  +#define TK_OR                              43
        12462  +#define TK_AND                             44
        12463  +#define TK_IS                              45
        12464  +#define TK_MATCH                           46
        12465  +#define TK_LIKE_KW                         47
        12466  +#define TK_BETWEEN                         48
        12467  +#define TK_IN                              49
        12468  +#define TK_ISNULL                          50
        12469  +#define TK_NOTNULL                         51
        12470  +#define TK_NE                              52
        12471  +#define TK_EQ                              53
        12472  +#define TK_GT                              54
        12473  +#define TK_LE                              55
        12474  +#define TK_LT                              56
        12475  +#define TK_GE                              57
        12476  +#define TK_ESCAPE                          58
        12477  +#define TK_ID                              59
        12478  +#define TK_COLUMNKW                        60
        12479  +#define TK_FOR                             61
        12480  +#define TK_IGNORE                          62
        12481  +#define TK_INITIALLY                       63
        12482  +#define TK_INSTEAD                         64
        12483  +#define TK_NO                              65
        12484  +#define TK_KEY                             66
        12485  +#define TK_OF                              67
        12486  +#define TK_OFFSET                          68
        12487  +#define TK_PRAGMA                          69
        12488  +#define TK_RAISE                           70
        12489  +#define TK_RECURSIVE                       71
        12490  +#define TK_REPLACE                         72
        12491  +#define TK_RESTRICT                        73
        12492  +#define TK_ROW                             74
        12493  +#define TK_TRIGGER                         75
        12494  +#define TK_VACUUM                          76
        12495  +#define TK_VIEW                            77
        12496  +#define TK_VIRTUAL                         78
        12497  +#define TK_WITH                            79
        12498  +#define TK_REINDEX                         80
        12499  +#define TK_RENAME                          81
        12500  +#define TK_CTIME_KW                        82
        12501  +#define TK_ANY                             83
 12469  12502   #define TK_BITAND                          84
 12470  12503   #define TK_BITOR                           85
 12471  12504   #define TK_LSHIFT                          86
 12472  12505   #define TK_RSHIFT                          87
 12473  12506   #define TK_PLUS                            88
 12474  12507   #define TK_MINUS                           89
 12475  12508   #define TK_STAR                            90
................................................................................
 12521  12554   #define TK_CASE                           136
 12522  12555   #define TK_WHEN                           137
 12523  12556   #define TK_THEN                           138
 12524  12557   #define TK_ELSE                           139
 12525  12558   #define TK_INDEX                          140
 12526  12559   #define TK_ALTER                          141
 12527  12560   #define TK_ADD                            142
 12528         -#define TK_TO_TEXT                        143
 12529         -#define TK_TO_BLOB                        144
 12530         -#define TK_TO_NUMERIC                     145
 12531         -#define TK_TO_INT                         146
 12532         -#define TK_TO_REAL                        147
 12533         -#define TK_ISNOT                          148
 12534         -#define TK_END_OF_FILE                    149
 12535         -#define TK_UNCLOSED_STRING                150
 12536         -#define TK_FUNCTION                       151
 12537         -#define TK_COLUMN                         152
 12538         -#define TK_AGG_FUNCTION                   153
 12539         -#define TK_AGG_COLUMN                     154
 12540         -#define TK_UMINUS                         155
 12541         -#define TK_UPLUS                          156
 12542         -#define TK_REGISTER                       157
 12543         -#define TK_VECTOR                         158
 12544         -#define TK_SELECT_COLUMN                  159
 12545         -#define TK_IF_NULL_ROW                    160
 12546         -#define TK_ASTERISK                       161
 12547         -#define TK_SPAN                           162
 12548         -#define TK_SPACE                          163
 12549         -#define TK_ILLEGAL                        164
        12561  +#define TK_ISNOT                          143
        12562  +#define TK_FUNCTION                       144
        12563  +#define TK_COLUMN                         145
        12564  +#define TK_AGG_FUNCTION                   146
        12565  +#define TK_AGG_COLUMN                     147
        12566  +#define TK_UMINUS                         148
        12567  +#define TK_UPLUS                          149
        12568  +#define TK_REGISTER                       150
        12569  +#define TK_VECTOR                         151
        12570  +#define TK_SELECT_COLUMN                  152
        12571  +#define TK_IF_NULL_ROW                    153
        12572  +#define TK_ASTERISK                       154
        12573  +#define TK_SPAN                           155
        12574  +#define TK_END_OF_FILE                    156
        12575  +#define TK_UNCLOSED_STRING                157
        12576  +#define TK_SPACE                          158
        12577  +#define TK_ILLEGAL                        159
 12550  12578   
 12551  12579   /* The token codes above must all fit in 8 bits */
 12552  12580   #define TKFLG_MASK           0xff  
 12553  12581   
 12554  12582   /* Flags that can be added to a token code when it is not
 12555  12583   ** being stored in a u8: */
 12556  12584   #define TKFLG_DONTFOLD       0x100  /* Omit constant folding optimizations */
................................................................................
 12662  12690   ** The default value of "20" was choosen to minimize the run-time of the
 12663  12691   ** speedtest1 test program with options: --shrink-memory --reprepare
 12664  12692   */
 12665  12693   #ifndef SQLITE_DEFAULT_PCACHE_INITSZ
 12666  12694   # define SQLITE_DEFAULT_PCACHE_INITSZ 20
 12667  12695   #endif
 12668  12696   
        12697  +/*
        12698  +** The compile-time options SQLITE_MMAP_READWRITE and 
        12699  +** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
        12700  +** You must choose one or the other (or neither) but not both.
        12701  +*/
        12702  +#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
        12703  +#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
        12704  +#endif
        12705  +
 12669  12706   /*
 12670  12707   ** GCC does not define the offsetof() macro so we'll have to do it
 12671  12708   ** ourselves.
 12672  12709   */
 12673  12710   #ifndef offsetof
 12674  12711   #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
 12675  12712   #endif
................................................................................
 13364  13401   SQLITE_PRIVATE int sqlite3BtreeCursor(
 13365  13402     Btree*,                              /* BTree containing table to open */
 13366  13403     int iTable,                          /* Index of root page */
 13367  13404     int wrFlag,                          /* 1 for writing.  0 for read-only */
 13368  13405     struct KeyInfo*,                     /* First argument to compare function */
 13369  13406     BtCursor *pCursor                    /* Space to write cursor structure */
 13370  13407   );
        13408  +SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
 13371  13409   SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
 13372  13410   SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
 13373  13411   SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
 13374  13412   #ifdef SQLITE_ENABLE_CURSOR_HINTS
 13375  13413   SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
 13376  13414   #endif
 13377  13415   
................................................................................
 13682  13720   /************** Include opcodes.h in the middle of vdbe.h ********************/
 13683  13721   /************** Begin file opcodes.h *****************************************/
 13684  13722   /* Automatically generated.  Do not edit */
 13685  13723   /* See the tool/mkopcodeh.tcl script for details */
 13686  13724   #define OP_Savepoint       0
 13687  13725   #define OP_AutoCommit      1
 13688  13726   #define OP_Transaction     2
 13689         -#define OP_SorterNext      3
 13690         -#define OP_PrevIfOpen      4
 13691         -#define OP_NextIfOpen      5
 13692         -#define OP_Prev            6
 13693         -#define OP_Next            7
        13727  +#define OP_SorterNext      3 /* jump                                       */
        13728  +#define OP_PrevIfOpen      4 /* jump                                       */
        13729  +#define OP_NextIfOpen      5 /* jump                                       */
        13730  +#define OP_Prev            6 /* jump                                       */
        13731  +#define OP_Next            7 /* jump                                       */
 13694  13732   #define OP_Checkpoint      8
 13695  13733   #define OP_JournalMode     9
 13696  13734   #define OP_Vacuum         10
 13697         -#define OP_VFilter        11 /* synopsis: iplan=r[P3] zplan='P4'           */
        13735  +#define OP_VFilter        11 /* jump, synopsis: iplan=r[P3] zplan='P4'     */
 13698  13736   #define OP_VUpdate        12 /* synopsis: data=r[P3@P2]                    */
 13699         -#define OP_Goto           13
 13700         -#define OP_Gosub          14
 13701         -#define OP_InitCoroutine  15
 13702         -#define OP_Yield          16
 13703         -#define OP_MustBeInt      17
 13704         -#define OP_Jump           18
        13737  +#define OP_Goto           13 /* jump                                       */
        13738  +#define OP_Gosub          14 /* jump                                       */
        13739  +#define OP_InitCoroutine  15 /* jump                                       */
        13740  +#define OP_Yield          16 /* jump                                       */
        13741  +#define OP_MustBeInt      17 /* jump                                       */
        13742  +#define OP_Jump           18 /* jump                                       */
 13705  13743   #define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
 13706         -#define OP_Once           20
 13707         -#define OP_If             21
 13708         -#define OP_IfNot          22
 13709         -#define OP_IfNullRow      23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
 13710         -#define OP_SeekLT         24 /* synopsis: key=r[P3@P4]                     */
 13711         -#define OP_SeekLE         25 /* synopsis: key=r[P3@P4]                     */
 13712         -#define OP_SeekGE         26 /* synopsis: key=r[P3@P4]                     */
 13713         -#define OP_SeekGT         27 /* synopsis: key=r[P3@P4]                     */
 13714         -#define OP_NoConflict     28 /* synopsis: key=r[P3@P4]                     */
 13715         -#define OP_NotFound       29 /* synopsis: key=r[P3@P4]                     */
 13716         -#define OP_Found          30 /* synopsis: key=r[P3@P4]                     */
 13717         -#define OP_SeekRowid      31 /* synopsis: intkey=r[P3]                     */
 13718         -#define OP_NotExists      32 /* synopsis: intkey=r[P3]                     */
 13719         -#define OP_Last           33
 13720         -#define OP_IfSmaller      34
 13721         -#define OP_SorterSort     35
 13722         -#define OP_Sort           36
 13723         -#define OP_Rewind         37
 13724         -#define OP_IdxLE          38 /* synopsis: key=r[P3@P4]                     */
 13725         -#define OP_IdxGT          39 /* synopsis: key=r[P3@P4]                     */
 13726         -#define OP_IdxLT          40 /* synopsis: key=r[P3@P4]                     */
 13727         -#define OP_IdxGE          41 /* synopsis: key=r[P3@P4]                     */
 13728         -#define OP_RowSetRead     42 /* synopsis: r[P3]=rowset(P1)                 */
 13729         -#define OP_RowSetTest     43 /* synopsis: if r[P3] in rowset(P1) goto P2   */
 13730         -#define OP_Program        44
 13731         -#define OP_FkIfZero       45 /* synopsis: if fkctr[P1]==0 goto P2          */
 13732         -#define OP_IfPos          46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
 13733         -#define OP_IfNotZero      47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
 13734         -#define OP_DecrJumpZero   48 /* synopsis: if (--r[P1])==0 goto P2          */
 13735         -#define OP_IncrVacuum     49
 13736         -#define OP_VNext          50
 13737         -#define OP_Init           51 /* synopsis: Start at P2                      */
 13738         -#define OP_Return         52
 13739         -#define OP_EndCoroutine   53
 13740         -#define OP_HaltIfNull     54 /* synopsis: if r[P3]=null halt               */
 13741         -#define OP_Halt           55
 13742         -#define OP_Integer        56 /* synopsis: r[P2]=P1                         */
 13743         -#define OP_Int64          57 /* synopsis: r[P2]=P4                         */
 13744         -#define OP_String         58 /* synopsis: r[P2]='P4' (len=P1)              */
 13745         -#define OP_Null           59 /* synopsis: r[P2..P3]=NULL                   */
 13746         -#define OP_SoftNull       60 /* synopsis: r[P1]=NULL                       */
 13747         -#define OP_Blob           61 /* synopsis: r[P2]=P4 (len=P1)                */
 13748         -#define OP_Variable       62 /* synopsis: r[P2]=parameter(P1,P4)           */
 13749         -#define OP_Move           63 /* synopsis: r[P2@P3]=r[P1@P3]                */
 13750         -#define OP_Copy           64 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */
 13751         -#define OP_SCopy          65 /* synopsis: r[P2]=r[P1]                      */
 13752         -#define OP_IntCopy        66 /* synopsis: r[P2]=r[P1]                      */
 13753         -#define OP_ResultRow      67 /* synopsis: output=r[P1@P2]                  */
 13754         -#define OP_CollSeq        68
 13755         -#define OP_Function0      69 /* synopsis: r[P3]=func(r[P2@P5])             */
 13756         -#define OP_Or             70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
 13757         -#define OP_And            71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
 13758         -#define OP_Function       72 /* synopsis: r[P3]=func(r[P2@P5])             */
 13759         -#define OP_AddImm         73 /* synopsis: r[P1]=r[P1]+P2                   */
 13760         -#define OP_RealAffinity   74
 13761         -#define OP_IsNull         75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
 13762         -#define OP_NotNull        76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
 13763         -#define OP_Ne             77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1]   */
 13764         -#define OP_Eq             78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1]   */
 13765         -#define OP_Gt             79 /* same as TK_GT, synopsis: IF r[P3]>r[P1]    */
 13766         -#define OP_Le             80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1]   */
 13767         -#define OP_Lt             81 /* same as TK_LT, synopsis: IF r[P3]<r[P1]    */
 13768         -#define OP_Ge             82 /* same as TK_GE, synopsis: IF r[P3]>=r[P1]   */
 13769         -#define OP_ElseNotEq      83 /* same as TK_ESCAPE                          */
        13744  +#define OP_Once           20 /* jump                                       */
        13745  +#define OP_If             21 /* jump                                       */
        13746  +#define OP_IfNot          22 /* jump                                       */
        13747  +#define OP_IfNullRow      23 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
        13748  +#define OP_SeekLT         24 /* jump, synopsis: key=r[P3@P4]               */
        13749  +#define OP_SeekLE         25 /* jump, synopsis: key=r[P3@P4]               */
        13750  +#define OP_SeekGE         26 /* jump, synopsis: key=r[P3@P4]               */
        13751  +#define OP_SeekGT         27 /* jump, synopsis: key=r[P3@P4]               */
        13752  +#define OP_NoConflict     28 /* jump, synopsis: key=r[P3@P4]               */
        13753  +#define OP_NotFound       29 /* jump, synopsis: key=r[P3@P4]               */
        13754  +#define OP_Found          30 /* jump, synopsis: key=r[P3@P4]               */
        13755  +#define OP_SeekRowid      31 /* jump, synopsis: intkey=r[P3]               */
        13756  +#define OP_NotExists      32 /* jump, synopsis: intkey=r[P3]               */
        13757  +#define OP_Last           33 /* jump                                       */
        13758  +#define OP_IfSmaller      34 /* jump                                       */
        13759  +#define OP_SorterSort     35 /* jump                                       */
        13760  +#define OP_Sort           36 /* jump                                       */
        13761  +#define OP_Rewind         37 /* jump                                       */
        13762  +#define OP_IdxLE          38 /* jump, synopsis: key=r[P3@P4]               */
        13763  +#define OP_IdxGT          39 /* jump, synopsis: key=r[P3@P4]               */
        13764  +#define OP_IdxLT          40 /* jump, synopsis: key=r[P3@P4]               */
        13765  +#define OP_IdxGE          41 /* jump, synopsis: key=r[P3@P4]               */
        13766  +#define OP_RowSetRead     42 /* jump, synopsis: r[P3]=rowset(P1)           */
        13767  +#define OP_Or             43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
        13768  +#define OP_And            44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
        13769  +#define OP_RowSetTest     45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
        13770  +#define OP_Program        46 /* jump                                       */
        13771  +#define OP_FkIfZero       47 /* jump, synopsis: if fkctr[P1]==0 goto P2    */
        13772  +#define OP_IfPos          48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
        13773  +#define OP_IfNotZero      49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
        13774  +#define OP_IsNull         50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
        13775  +#define OP_NotNull        51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
        13776  +#define OP_Ne             52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
        13777  +#define OP_Eq             53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
        13778  +#define OP_Gt             54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
        13779  +#define OP_Le             55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
        13780  +#define OP_Lt             56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
        13781  +#define OP_Ge             57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
        13782  +#define OP_ElseNotEq      58 /* jump, same as TK_ESCAPE                    */
        13783  +#define OP_DecrJumpZero   59 /* jump, synopsis: if (--r[P1])==0 goto P2    */
        13784  +#define OP_IncrVacuum     60 /* jump                                       */
        13785  +#define OP_VNext          61 /* jump                                       */
        13786  +#define OP_Init           62 /* jump, synopsis: Start at P2                */
        13787  +#define OP_Return         63
        13788  +#define OP_EndCoroutine   64
        13789  +#define OP_HaltIfNull     65 /* synopsis: if r[P3]=null halt               */
        13790  +#define OP_Halt           66
        13791  +#define OP_Integer        67 /* synopsis: r[P2]=P1                         */
        13792  +#define OP_Int64          68 /* synopsis: r[P2]=P4                         */
        13793  +#define OP_String         69 /* synopsis: r[P2]='P4' (len=P1)              */
        13794  +#define OP_Null           70 /* synopsis: r[P2..P3]=NULL                   */
        13795  +#define OP_SoftNull       71 /* synopsis: r[P1]=NULL                       */
        13796  +#define OP_Blob           72 /* synopsis: r[P2]=P4 (len=P1)                */
        13797  +#define OP_Variable       73 /* synopsis: r[P2]=parameter(P1,P4)           */
        13798  +#define OP_Move           74 /* synopsis: r[P2@P3]=r[P1@P3]                */
        13799  +#define OP_Copy           75 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */
        13800  +#define OP_SCopy          76 /* synopsis: r[P2]=r[P1]                      */
        13801  +#define OP_IntCopy        77 /* synopsis: r[P2]=r[P1]                      */
        13802  +#define OP_ResultRow      78 /* synopsis: output=r[P1@P2]                  */
        13803  +#define OP_CollSeq        79
        13804  +#define OP_AddImm         80 /* synopsis: r[P1]=r[P1]+P2                   */
        13805  +#define OP_RealAffinity   81
        13806  +#define OP_Cast           82 /* synopsis: affinity(r[P1])                  */
        13807  +#define OP_Permutation    83
 13770  13808   #define OP_BitAnd         84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
 13771  13809   #define OP_BitOr          85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
 13772  13810   #define OP_ShiftLeft      86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
 13773  13811   #define OP_ShiftRight     87 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
 13774  13812   #define OP_Add            88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
 13775  13813   #define OP_Subtract       89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
 13776  13814   #define OP_Multiply       90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
 13777  13815   #define OP_Divide         91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
 13778  13816   #define OP_Remainder      92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
 13779  13817   #define OP_Concat         93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
 13780         -#define OP_Cast           94 /* synopsis: affinity(r[P1])                  */
        13818  +#define OP_Compare        94 /* synopsis: r[P1@P3] <-> r[P2@P3]            */
 13781  13819   #define OP_BitNot         95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
 13782         -#define OP_Permutation    96
        13820  +#define OP_Column         96 /* synopsis: r[P3]=PX                         */
 13783  13821   #define OP_String8        97 /* same as TK_STRING, synopsis: r[P2]='P4'    */
 13784         -#define OP_Compare        98 /* synopsis: r[P1@P3] <-> r[P2@P3]            */
 13785         -#define OP_Column         99 /* synopsis: r[P3]=PX                         */
 13786         -#define OP_Affinity      100 /* synopsis: affinity(r[P1@P2])               */
 13787         -#define OP_MakeRecord    101 /* synopsis: r[P3]=mkrec(r[P1@P2])            */
 13788         -#define OP_Count         102 /* synopsis: r[P2]=count()                    */
 13789         -#define OP_ReadCookie    103
 13790         -#define OP_SetCookie     104
 13791         -#define OP_ReopenIdx     105 /* synopsis: root=P2 iDb=P3                   */
 13792         -#define OP_OpenRead      106 /* synopsis: root=P2 iDb=P3                   */
 13793         -#define OP_OpenWrite     107 /* synopsis: root=P2 iDb=P3                   */
 13794         -#define OP_OpenDup       108
 13795         -#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2                       */
 13796         -#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2                       */
 13797         -#define OP_SorterOpen    111
 13798         -#define OP_SequenceTest  112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2   */
 13799         -#define OP_OpenPseudo    113 /* synopsis: P3 columns in r[P2]              */
 13800         -#define OP_Close         114
 13801         -#define OP_ColumnsUsed   115
 13802         -#define OP_Sequence      116 /* synopsis: r[P2]=cursor[P1].ctr++           */
 13803         -#define OP_NewRowid      117 /* synopsis: r[P2]=rowid                      */
 13804         -#define OP_Insert        118 /* synopsis: intkey=r[P3] data=r[P2]          */
 13805         -#define OP_InsertInt     119 /* synopsis: intkey=P3 data=r[P2]             */
 13806         -#define OP_Delete        120
 13807         -#define OP_ResetCount    121
 13808         -#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
 13809         -#define OP_SorterData    123 /* synopsis: r[P2]=data                       */
 13810         -#define OP_RowData       124 /* synopsis: r[P2]=data                       */
 13811         -#define OP_Rowid         125 /* synopsis: r[P2]=rowid                      */
 13812         -#define OP_NullRow       126
 13813         -#define OP_SorterInsert  127 /* synopsis: key=r[P2]                        */
 13814         -#define OP_IdxInsert     128 /* synopsis: key=r[P2]                        */
 13815         -#define OP_IdxDelete     129 /* synopsis: key=r[P2@P3]                     */
 13816         -#define OP_DeferredSeek  130 /* synopsis: Move P3 to P1.rowid if needed    */
 13817         -#define OP_IdxRowid      131 /* synopsis: r[P2]=rowid                      */
        13822  +#define OP_Affinity       98 /* synopsis: affinity(r[P1@P2])               */
        13823  +#define OP_MakeRecord     99 /* synopsis: r[P3]=mkrec(r[P1@P2])            */
        13824  +#define OP_Count         100 /* synopsis: r[P2]=count()                    */
        13825  +#define OP_ReadCookie    101
        13826  +#define OP_SetCookie     102
        13827  +#define OP_ReopenIdx     103 /* synopsis: root=P2 iDb=P3                   */
        13828  +#define OP_OpenRead      104 /* synopsis: root=P2 iDb=P3                   */
        13829  +#define OP_OpenWrite     105 /* synopsis: root=P2 iDb=P3                   */
        13830  +#define OP_OpenDup       106
        13831  +#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2                       */
        13832  +#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2                       */
        13833  +#define OP_SorterOpen    109
        13834  +#define OP_SequenceTest  110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2   */
        13835  +#define OP_OpenPseudo    111 /* synopsis: P3 columns in r[P2]              */
        13836  +#define OP_Close         112
        13837  +#define OP_ColumnsUsed   113
        13838  +#define OP_Sequence      114 /* synopsis: r[P2]=cursor[P1].ctr++           */
        13839  +#define OP_NewRowid      115 /* synopsis: r[P2]=rowid                      */
        13840  +#define OP_Insert        116 /* synopsis: intkey=r[P3] data=r[P2]          */
        13841  +#define OP_InsertInt     117 /* synopsis: intkey=P3 data=r[P2]             */
        13842  +#define OP_Delete        118
        13843  +#define OP_ResetCount    119
        13844  +#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
        13845  +#define OP_SorterData    121 /* synopsis: r[P2]=data                       */
        13846  +#define OP_RowData       122 /* synopsis: r[P2]=data                       */
        13847  +#define OP_Rowid         123 /* synopsis: r[P2]=rowid                      */
        13848  +#define OP_NullRow       124
        13849  +#define OP_SeekEnd       125
        13850  +#define OP_SorterInsert  126 /* synopsis: key=r[P2]                        */
        13851  +#define OP_IdxInsert     127 /* synopsis: key=r[P2]                        */
        13852  +#define OP_IdxDelete     128 /* synopsis: key=r[P2@P3]                     */
        13853  +#define OP_DeferredSeek  129 /* synopsis: Move P3 to P1.rowid if needed    */
        13854  +#define OP_IdxRowid      130 /* synopsis: r[P2]=rowid                      */
        13855  +#define OP_Destroy       131
 13818  13856   #define OP_Real          132 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
 13819         -#define OP_Destroy       133
 13820         -#define OP_Clear         134
 13821         -#define OP_ResetSorter   135
 13822         -#define OP_CreateIndex   136 /* synopsis: r[P2]=root iDb=P1                */
 13823         -#define OP_CreateTable   137 /* synopsis: r[P2]=root iDb=P1                */
 13824         -#define OP_SqlExec       138
 13825         -#define OP_ParseSchema   139
 13826         -#define OP_LoadAnalysis  140
 13827         -#define OP_DropTable     141
 13828         -#define OP_DropIndex     142
 13829         -#define OP_DropTrigger   143
 13830         -#define OP_IntegrityCk   144
 13831         -#define OP_RowSetAdd     145 /* synopsis: rowset(P1)=r[P2]                 */
 13832         -#define OP_Param         146
 13833         -#define OP_FkCounter     147 /* synopsis: fkctr[P1]+=P2                    */
 13834         -#define OP_MemMax        148 /* synopsis: r[P1]=max(r[P1],r[P2])           */
 13835         -#define OP_OffsetLimit   149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
 13836         -#define OP_AggStep0      150 /* synopsis: accum=r[P3] step(r[P2@P5])       */
 13837         -#define OP_AggStep       151 /* synopsis: accum=r[P3] step(r[P2@P5])       */
 13838         -#define OP_AggFinal      152 /* synopsis: accum=r[P1] N=P2                 */
 13839         -#define OP_Expire        153
 13840         -#define OP_TableLock     154 /* synopsis: iDb=P1 root=P2 write=P3          */
 13841         -#define OP_VBegin        155
 13842         -#define OP_VCreate       156
 13843         -#define OP_VDestroy      157
 13844         -#define OP_VOpen         158
 13845         -#define OP_VColumn       159 /* synopsis: r[P3]=vcolumn(P2)                */
 13846         -#define OP_VRename       160
 13847         -#define OP_Pagecount     161
 13848         -#define OP_MaxPgcnt      162
 13849         -#define OP_CursorHint    163
 13850         -#define OP_Noop          164
 13851         -#define OP_Explain       165
        13857  +#define OP_Clear         133
        13858  +#define OP_ResetSorter   134
        13859  +#define OP_CreateBtree   135 /* synopsis: r[P2]=root iDb=P1 flags=P3       */
        13860  +#define OP_SqlExec       136
        13861  +#define OP_ParseSchema   137
        13862  +#define OP_LoadAnalysis  138
        13863  +#define OP_DropTable     139
        13864  +#define OP_DropIndex     140
        13865  +#define OP_DropTrigger   141
        13866  +#define OP_IntegrityCk   142
        13867  +#define OP_RowSetAdd     143 /* synopsis: rowset(P1)=r[P2]                 */
        13868  +#define OP_Param         144
        13869  +#define OP_FkCounter     145 /* synopsis: fkctr[P1]+=P2                    */
        13870  +#define OP_MemMax        146 /* synopsis: r[P1]=max(r[P1],r[P2])           */
        13871  +#define OP_OffsetLimit   147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
        13872  +#define OP_AggStep0      148 /* synopsis: accum=r[P3] step(r[P2@P5])       */
        13873  +#define OP_AggStep       149 /* synopsis: accum=r[P3] step(r[P2@P5])       */
        13874  +#define OP_AggFinal      150 /* synopsis: accum=r[P1] N=P2                 */
        13875  +#define OP_Expire        151
        13876  +#define OP_TableLock     152 /* synopsis: iDb=P1 root=P2 write=P3          */
        13877  +#define OP_VBegin        153
        13878  +#define OP_VCreate       154
        13879  +#define OP_VDestroy      155
        13880  +#define OP_VOpen         156
        13881  +#define OP_VColumn       157 /* synopsis: r[P3]=vcolumn(P2)                */
        13882  +#define OP_VRename       158
        13883  +#define OP_Pagecount     159
        13884  +#define OP_MaxPgcnt      160
        13885  +#define OP_PureFunc0     161
        13886  +#define OP_Function0     162 /* synopsis: r[P3]=func(r[P2@P5])             */
        13887  +#define OP_PureFunc      163
        13888  +#define OP_Function      164 /* synopsis: r[P3]=func(r[P2@P5])             */
        13889  +#define OP_CursorHint    165
        13890  +#define OP_Noop          166
        13891  +#define OP_Explain       167
 13852  13892   
 13853  13893   /* Properties such as "out2" or "jump" that are specified in
 13854  13894   ** comments following the "case" for each opcode in the vdbe.c
 13855  13895   ** are encoded into bitvectors as follows:
 13856  13896   */
 13857  13897   #define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */
 13858  13898   #define OPFLG_IN1         0x02  /* in1:   P1 is an input */
................................................................................
 13862  13902   #define OPFLG_OUT3        0x20  /* out3:  P3 is an output */
 13863  13903   #define OPFLG_INITIALIZER {\
 13864  13904   /*   0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\
 13865  13905   /*   8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\
 13866  13906   /*  16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\
 13867  13907   /*  24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
 13868  13908   /*  32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
 13869         -/*  40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\
 13870         -/*  48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\
 13871         -/*  56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\
 13872         -/*  64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x26, 0x26,\
 13873         -/*  72 */ 0x00, 0x02, 0x02, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
 13874         -/*  80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\
 13875         -/*  88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x02, 0x12,\
 13876         -/*  96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
        13909  +/*  40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
        13910  +/*  48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
        13911  +/*  56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\
        13912  +/*  64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\
        13913  +/*  72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
        13914  +/*  80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\
        13915  +/*  88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
        13916  +/*  96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
 13877  13917   /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
 13878         -/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
 13879         -/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04,\
 13880         -/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\
 13881         -/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
 13882         -/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\
 13883         -/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
 13884         -/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,}
        13918  +/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\
        13919  +/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x04,\
        13920  +/* 128 */ 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10,\
        13921  +/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\
        13922  +/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\
        13923  +/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
        13924  +/* 160 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
        13925  +}
 13885  13926   
 13886  13927   /* The sqlite3P2Values() routine is able to run faster if it knows
 13887  13928   ** the value of the largest JUMP opcode.  The smaller the maximum
 13888  13929   ** JUMP opcode the better, so the mkopcodeh.tcl script that
 13889  13930   ** generated this include file strives to group all JUMP opcodes
 13890  13931   ** together near the beginning of the list.
 13891  13932   */
 13892         -#define SQLITE_MX_JUMP_OPCODE  83  /* Maximum JUMP opcode */
        13933  +#define SQLITE_MX_JUMP_OPCODE  62  /* Maximum JUMP opcode */
 13893  13934   
 13894  13935   /************** End of opcodes.h *********************************************/
 13895  13936   /************** Continuing where we left off in vdbe.h ***********************/
 13896  13937   
 13897  13938   /*
 13898  13939   ** Additional non-public SQLITE_PREPARE_* flags
 13899  13940   */
................................................................................
 13975  14016   
 13976  14017   typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
 13977  14018   SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
 13978  14019   
 13979  14020   #ifndef SQLITE_OMIT_TRIGGER
 13980  14021   SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
 13981  14022   #endif
        14023  +
        14024  +SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
 13982  14025   
 13983  14026   /* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
 13984  14027   ** each VDBE opcode.
 13985  14028   **
 13986  14029   ** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
 13987  14030   ** comments in VDBE programs that show key decision points in the code
 13988  14031   ** generator.
................................................................................
 14201  14244   
 14202  14245   /* Functions used to obtain and release page references. */ 
 14203  14246   SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
 14204  14247   SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
 14205  14248   SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
 14206  14249   SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
 14207  14250   SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
        14251  +SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*);
 14208  14252   
 14209  14253   /* Operations on page references. */
 14210  14254   SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
 14211  14255   SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
 14212  14256   SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
 14213  14257   SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
 14214  14258   SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); 
................................................................................
 14337  14381     ** Elements above, except pCache, are public.  All that follow are 
 14338  14382     ** private to pcache.c and should not be accessed by other modules.
 14339  14383     ** pCache is grouped with the public elements for efficiency.
 14340  14384     */
 14341  14385     i16 nRef;                      /* Number of users of this page */
 14342  14386     PgHdr *pDirtyNext;             /* Next element in list of dirty pages */
 14343  14387     PgHdr *pDirtyPrev;             /* Previous element in list of dirty pages */
        14388  +                          /* NB: pDirtyNext and pDirtyPrev are undefined if the
        14389  +                          ** PgHdr object is not dirty */
 14344  14390   };
 14345  14391   
 14346  14392   /* Bit values for PgHdr.flags */
 14347  14393   #define PGHDR_CLEAN           0x001  /* Page not on the PCache.pDirty list */
 14348  14394   #define PGHDR_DIRTY           0x002  /* Page is on the PCache.pDirty list */
 14349  14395   #define PGHDR_WRITEABLE       0x004  /* Journaled and ready to modify */
 14350  14396   #define PGHDR_NEED_SYNC       0x008  /* Fsync the rollback journal before
................................................................................
 14930  14976   ** DB_UnresetViews means that one or more views have column names that
 14931  14977   ** have been filled out.  If the schema changes, these column names might
 14932  14978   ** changes and so the view will need to be reset.
 14933  14979   */
 14934  14980   #define DB_SchemaLoaded    0x0001  /* The schema has been loaded */
 14935  14981   #define DB_UnresetViews    0x0002  /* Some views have defined column names */
 14936  14982   #define DB_Empty           0x0004  /* The file is empty (length 0 bytes) */
        14983  +#define DB_ResetWanted     0x0008  /* Reset the schema when nSchemaLock==0 */
 14937  14984   
 14938  14985   /*
 14939  14986   ** The number of different kinds of things that can be limited
 14940  14987   ** using the sqlite3_limit() interface.
 14941  14988   */
 14942  14989   #define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
 14943  14990   
................................................................................
 14961  15008   ** schema information, the Lookaside.bEnabled flag is cleared so that
 14962  15009   ** lookaside allocations are not used to construct the schema objects.
 14963  15010   */
 14964  15011   struct Lookaside {
 14965  15012     u32 bDisable;           /* Only operate the lookaside when zero */
 14966  15013     u16 sz;                 /* Size of each buffer in bytes */
 14967  15014     u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
 14968         -  int nOut;               /* Number of buffers currently checked out */
 14969         -  int mxOut;              /* Highwater mark for nOut */
 14970         -  int anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
        15015  +  u32 nSlot;              /* Number of lookaside slots allocated */
        15016  +  u32 anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
        15017  +  LookasideSlot *pInit;   /* List of buffers not previously used */
 14971  15018     LookasideSlot *pFree;   /* List of available buffers */
 14972  15019     void *pStart;           /* First byte of available memory space */
 14973  15020     void *pEnd;             /* First byte past end of available space */
 14974  15021   };
 14975  15022   struct LookasideSlot {
 14976  15023     LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
 14977  15024   };
................................................................................
 15042  15089   struct sqlite3 {
 15043  15090     sqlite3_vfs *pVfs;            /* OS Interface */
 15044  15091     struct Vdbe *pVdbe;           /* List of active virtual machines */
 15045  15092     CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
 15046  15093     sqlite3_mutex *mutex;         /* Connection mutex */
 15047  15094     Db *aDb;                      /* All backends */
 15048  15095     int nDb;                      /* Number of backends currently in use */
 15049         -  int flags;                    /* Miscellaneous flags. See below */
        15096  +  u32 mDbFlags;                 /* flags recording internal state */
        15097  +  u32 flags;                    /* flags settable by pragmas. See below */
 15050  15098     i64 lastRowid;                /* ROWID of most recent insert (see above) */
 15051  15099     i64 szMmap;                   /* Default mmap_size setting */
        15100  +  u32 nSchemaLock;              /* Do not reset the schema when non-zero */
 15052  15101     unsigned int openFlags;       /* Flags passed to sqlite3_vfs.xOpen() */
 15053  15102     int errCode;                  /* Most recent error code (SQLITE_*) */
 15054  15103     int errMask;                  /* & result codes with this before returning */
 15055  15104     int iSysErrno;                /* Errno value from last system error */
 15056  15105     u16 dbOptFlags;               /* Flags to enable/disable optimizations */
 15057  15106     u8 enc;                       /* Text encoding */
 15058  15107     u8 autoCommit;                /* The auto-commit flag. */
................................................................................
 15196  15245   #define SQLITE_ReadUncommit   0x00000400  /* READ UNCOMMITTED in shared-cache */
 15197  15246   #define SQLITE_NoCkptOnClose  0x00000800  /* No checkpoint on close()/DETACH */
 15198  15247   #define SQLITE_ReverseOrder   0x00001000  /* Reverse unordered SELECTs */
 15199  15248   #define SQLITE_RecTriggers    0x00002000  /* Enable recursive triggers */
 15200  15249   #define SQLITE_ForeignKeys    0x00004000  /* Enforce foreign key constraints  */
 15201  15250   #define SQLITE_AutoIndex      0x00008000  /* Enable automatic indexes */
 15202  15251   #define SQLITE_LoadExtension  0x00010000  /* Enable load_extension */
 15203         -#define SQLITE_EnableTrigger  0x00020000  /* True to enable triggers */
 15204         -#define SQLITE_DeferFKs       0x00040000  /* Defer all FK constraints */
 15205         -#define SQLITE_QueryOnly      0x00080000  /* Disable database changes */
 15206         -#define SQLITE_CellSizeCk     0x00100000  /* Check btree cell sizes on load */
 15207         -#define SQLITE_Fts3Tokenizer  0x00200000  /* Enable fts3_tokenizer(2) */
 15208         -#define SQLITE_EnableQPSG     0x00400000  /* Query Planner Stability Guarantee */
 15209         -/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and
 15210         -** could be factored out into a separate bit vector of the sqlite3 object. */
 15211         -#define SQLITE_InternChanges  0x00800000  /* Uncommitted Hash table changes */
 15212         -#define SQLITE_LoadExtFunc    0x01000000  /* Enable load_extension() SQL func */
 15213         -#define SQLITE_PreferBuiltin  0x02000000  /* Preference to built-in funcs */
 15214         -#define SQLITE_Vacuum         0x04000000  /* Currently in a VACUUM */
        15252  +#define SQLITE_LoadExtFunc    0x00020000  /* Enable load_extension() SQL func */
        15253  +#define SQLITE_EnableTrigger  0x00040000  /* True to enable triggers */
        15254  +#define SQLITE_DeferFKs       0x00080000  /* Defer all FK constraints */
        15255  +#define SQLITE_QueryOnly      0x00100000  /* Disable database changes */
        15256  +#define SQLITE_CellSizeCk     0x00200000  /* Check btree cell sizes on load */
        15257  +#define SQLITE_Fts3Tokenizer  0x00400000  /* Enable fts3_tokenizer(2) */
        15258  +#define SQLITE_EnableQPSG     0x00800000  /* Query Planner Stability Guarantee */
 15215  15259   /* Flags used only if debugging */
 15216  15260   #ifdef SQLITE_DEBUG
 15217  15261   #define SQLITE_SqlTrace       0x08000000  /* Debug print SQL as it executes */
 15218  15262   #define SQLITE_VdbeListing    0x10000000  /* Debug listings of VDBE programs */
 15219  15263   #define SQLITE_VdbeTrace      0x20000000  /* True to trace VDBE execution */
 15220  15264   #define SQLITE_VdbeAddopTrace 0x40000000  /* Trace sqlite3VdbeAddOp() calls */
 15221  15265   #define SQLITE_VdbeEQP        0x80000000  /* Debug EXPLAIN QUERY PLAN */
 15222  15266   #endif
 15223  15267   
        15268  +/*
        15269  +** Allowed values for sqlite3.mDbFlags
        15270  +*/
        15271  +#define DBFLAG_SchemaChange   0x0001  /* Uncommitted Hash table changes */
        15272  +#define DBFLAG_PreferBuiltin  0x0002  /* Preference to built-in funcs */
        15273  +#define DBFLAG_Vacuum         0x0004  /* Currently in a VACUUM */
 15224  15274   
 15225  15275   /*
 15226  15276   ** Bits of the sqlite3.dbOptFlags field that are used by the
 15227  15277   ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
 15228  15278   ** selectively disable various optimizations.
 15229  15279   */
 15230  15280   #define SQLITE_QueryFlattener 0x0001   /* Query flattening */
 15231  15281   #define SQLITE_ColumnCache    0x0002   /* Column cache */
 15232  15282   #define SQLITE_GroupByOrder   0x0004   /* GROUPBY cover of ORDERBY */
 15233  15283   #define SQLITE_FactorOutConst 0x0008   /* Constant factoring */
 15234         -/*                not used    0x0010   // Was: SQLITE_IdxRealAsInt */
 15235         -#define SQLITE_DistinctOpt    0x0020   /* DISTINCT using indexes */
 15236         -#define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
 15237         -#define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
 15238         -#define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
 15239         -#define SQLITE_Transitive     0x0200   /* Transitive constraints */
 15240         -#define SQLITE_OmitNoopJoin   0x0400   /* Omit unused tables in joins */
        15284  +#define SQLITE_DistinctOpt    0x0010   /* DISTINCT using indexes */
        15285  +#define SQLITE_CoverIdxScan   0x0020   /* Covering index scans */
        15286  +#define SQLITE_OrderByIdxJoin 0x0040   /* ORDER BY of joins via index */
        15287  +#define SQLITE_Transitive     0x0080   /* Transitive constraints */
        15288  +#define SQLITE_OmitNoopJoin   0x0100   /* Omit unused tables in joins */
        15289  +#define SQLITE_CountOfView    0x0200   /* The count-of-view optimization */
        15290  +#define SQLITE_CursorHints    0x0400   /* Add OP_CursorHint opcodes */
 15241  15291   #define SQLITE_Stat34         0x0800   /* Use STAT3 or STAT4 data */
 15242         -#define SQLITE_CountOfView    0x1000   /* The count-of-view optimization */
 15243         -#define SQLITE_CursorHints    0x2000   /* Add OP_CursorHint opcodes */
        15292  +   /* TH3 expects the Stat34  ^^^^^^ value to be 0x0800.  Don't change it */
 15244  15293   #define SQLITE_AllOpts        0xffff   /* All optimizations */
 15245  15294   
 15246  15295   /*
 15247  15296   ** Macros for testing whether or not optimizations are enabled or disabled.
 15248  15297   */
 15249  15298   #define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
 15250  15299   #define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)
................................................................................
 15354  15403   **   VFUNCTION(zName, nArg, iArg, bNC, xFunc)
 15355  15404   **     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
 15356  15405   **
 15357  15406   **   DFUNCTION(zName, nArg, iArg, bNC, xFunc)
 15358  15407   **     Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
 15359  15408   **     adds the SQLITE_FUNC_SLOCHNG flag.  Used for date & time functions
 15360  15409   **     and functions like sqlite_version() that can change, but not during
 15361         -**     a single query.
        15410  +**     a single query.  The iArg is ignored.  The user-data is always set
        15411  +**     to a NULL pointer.  The bNC parameter is not used.
        15412  +**
        15413  +**   PURE_DATE(zName, nArg, iArg, bNC, xFunc)
        15414  +**     Used for "pure" date/time functions, this macro is like DFUNCTION
        15415  +**     except that it does set the SQLITE_FUNC_CONSTANT flags.  iArg is
        15416  +**     ignored and the user-data for these functions is set to an 
        15417  +**     arbitrary non-NULL pointer.  The bNC parameter is not used.
 15362  15418   **
 15363  15419   **   AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
 15364  15420   **     Used to create an aggregate function definition implemented by
 15365  15421   **     the C functions xStep and xFinal. The first four parameters
 15366  15422   **     are interpreted in the same way as the first 4 parameters to
 15367  15423   **     FUNCTION().
 15368  15424   **
................................................................................
 15377  15433   #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
 15378  15434     {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
 15379  15435      SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
 15380  15436   #define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
 15381  15437     {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
 15382  15438      SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
 15383  15439   #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
 15384         -  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
 15385         -   SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
        15440  +  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
        15441  +   0, 0, xFunc, 0, #zName, {0} }
        15442  +#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
        15443  +  {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
        15444  +   (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} }
 15386  15445   #define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
 15387  15446     {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
 15388  15447      SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
 15389  15448   #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
 15390  15449     {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
 15391  15450      pArg, 0, xFunc, 0, #zName, }
 15392  15451   #define LIKEFUNC(zName, nArg, arg, flags) \
................................................................................
 15757  15816   ** Note that aSortOrder[] and aColl[] have nField+1 slots.  There
 15758  15817   ** are nField slots for the columns of an index then one extra slot
 15759  15818   ** for the rowid at the end.
 15760  15819   */
 15761  15820   struct KeyInfo {
 15762  15821     u32 nRef;           /* Number of references to this KeyInfo object */
 15763  15822     u8 enc;             /* Text encoding - one of the SQLITE_UTF* values */
 15764         -  u16 nField;         /* Number of key columns in the index */
 15765         -  u16 nXField;        /* Number of columns beyond the key columns */
        15823  +  u16 nKeyField;      /* Number of key columns in the index */
        15824  +  u16 nAllField;      /* Total columns, including key plus others */
 15766  15825     sqlite3 *db;        /* The database connection */
 15767  15826     u8 *aSortOrder;     /* Sort order for each column. */
 15768  15827     CollSeq *aColl[1];  /* Collating sequence for each term of the key */
 15769  15828   };
 15770  15829   
 15771  15830   /*
 15772  15831   ** This object holds a record which has been parsed out into individual
................................................................................
 15805  15864   */
 15806  15865   struct UnpackedRecord {
 15807  15866     KeyInfo *pKeyInfo;  /* Collation and sort-order information */
 15808  15867     Mem *aMem;          /* Values */
 15809  15868     u16 nField;         /* Number of entries in apMem[] */
 15810  15869     i8 default_rc;      /* Comparison result if keys are equal */
 15811  15870     u8 errCode;         /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
 15812         -  i8 r1;              /* Value to return if (lhs > rhs) */
 15813         -  i8 r2;              /* Value to return if (rhs < lhs) */
        15871  +  i8 r1;              /* Value to return if (lhs < rhs) */
        15872  +  i8 r2;              /* Value to return if (lhs > rhs) */
 15814  15873     u8 eqSeen;          /* True if an equality comparison has been seen */
 15815  15874   };
 15816  15875   
 15817  15876   
 15818  15877   /*
 15819  15878   ** Each SQL index is represented in memory by an
 15820  15879   ** instance of the following structure.
................................................................................
 16090  16149                            ** TK_SELECT_COLUMN: column of the result vector */
 16091  16150     i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
 16092  16151     i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
 16093  16152     u8 op2;                /* TK_REGISTER: original value of Expr.op
 16094  16153                            ** TK_COLUMN: the value of p5 for OP_Column
 16095  16154                            ** TK_AGG_FUNCTION: nesting depth */
 16096  16155     AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
 16097         -  Table *pTab;           /* Table for TK_COLUMN expressions. */
        16156  +  Table *pTab;           /* Table for TK_COLUMN expressions.  Can be NULL
        16157  +                         ** for a column of an index on an expression */
 16098  16158   };
 16099  16159   
 16100  16160   /*
 16101  16161   ** The following are the meanings of bits in the Expr.flags field.
 16102  16162   */
 16103  16163   #define EP_FromJoin  0x000001 /* Originates in ON/USING clause of outer join */
 16104  16164   #define EP_Agg       0x000002 /* Contains one or more aggregate functions */
................................................................................
 16178  16238   ** column expression as it exists in a SELECT statement.  However, if
 16179  16239   ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
 16180  16240   ** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
 16181  16241   ** form is used for name resolution with nested FROM clauses.
 16182  16242   */
 16183  16243   struct ExprList {
 16184  16244     int nExpr;             /* Number of expressions on the list */
 16185         -  int nAlloc;            /* Number of a[] slots allocated */
 16186  16245     struct ExprList_item { /* For each expression in the list */
 16187  16246       Expr *pExpr;            /* The parse tree for this expression */
 16188  16247       char *zName;            /* Token associated with this expression */
 16189  16248       char *zSpan;            /* Original text of the expression */
 16190  16249       u8 sortOrder;           /* 1 for DESC or 0 for ASC */
 16191  16250       unsigned done :1;       /* A flag to indicate when processing is finished */
 16192  16251       unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
................................................................................
 16679  16738     int nRangeReg;       /* Size of the temporary register block */
 16680  16739     int iRangeReg;       /* First register in temporary register block */
 16681  16740     int nErr;            /* Number of errors seen */
 16682  16741     int nTab;            /* Number of previously allocated VDBE cursors */
 16683  16742     int nMem;            /* Number of memory cells used so far */
 16684  16743     int nOpAlloc;        /* Number of slots allocated for Vdbe.aOp[] */
 16685  16744     int szOpAlloc;       /* Bytes of memory space allocated for Vdbe.aOp[] */
 16686         -  int ckBase;          /* Base register of data during check constraints */
 16687         -  int iSelfTab;        /* Table of an index whose exprs are being coded */
        16745  +  int iSelfTab;        /* Table for associated with an index on expr, or negative
        16746  +                       ** of the base register during check-constraint eval */
 16688  16747     int iCacheLevel;     /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
 16689  16748     int iCacheCnt;       /* Counter used to generate aColCache[].lru values */
 16690  16749     int nLabel;          /* Number of labels used */
 16691  16750     int *aLabel;         /* Space to hold the labels */
 16692  16751     ExprList *pConstExpr;/* Constant expressions */
 16693  16752     Token constraintName;/* Name of the constraint currently being parsed */
 16694  16753     yDbMask writeMask;   /* Start a write transaction on these databases */
................................................................................
 16703  16762   #ifndef SQLITE_OMIT_SHARED_CACHE
 16704  16763     int nTableLock;        /* Number of locks in aTableLock */
 16705  16764     TableLock *aTableLock; /* Required table locks for shared-cache mode */
 16706  16765   #endif
 16707  16766     AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
 16708  16767     Parse *pToplevel;    /* Parse structure for main program (or NULL) */
 16709  16768     Table *pTriggerTab;  /* Table triggers are being coded for */
 16710         -  int addrCrTab;       /* Address of OP_CreateTable opcode on CREATE TABLE */
        16769  +  int addrCrTab;       /* Address of OP_CreateBtree opcode on CREATE TABLE */
 16711  16770     u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
 16712  16771     u32 oldmask;         /* Mask of old.* columns referenced */
 16713  16772     u32 newmask;         /* Mask of new.* columns referenced */
 16714  16773     u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
 16715  16774     u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
 16716  16775     u8 disableTriggers;  /* True to disable triggers */
 16717  16776   
................................................................................
 16932  16991   
 16933  16992   /*
 16934  16993   ** An objected used to accumulate the text of a string where we
 16935  16994   ** do not necessarily know how big the string will be in the end.
 16936  16995   */
 16937  16996   struct StrAccum {
 16938  16997     sqlite3 *db;         /* Optional database for lookaside.  Can be NULL */
 16939         -  char *zBase;         /* A base allocation.  Not from malloc. */
 16940  16998     char *zText;         /* The string collected so far */
 16941         -  u32  nChar;          /* Length of the string so far */
 16942  16999     u32  nAlloc;         /* Amount of space allocated in zText */
 16943  17000     u32  mxAlloc;        /* Maximum allowed allocation.  0 for no malloc usage */
        17001  +  u32  nChar;          /* Length of the string so far */
 16944  17002     u8   accError;       /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
 16945  17003     u8   printfFlags;    /* SQLITE_PRINTF flags below */
 16946  17004   };
 16947  17005   #define STRACCUM_NOMEM   1
 16948  17006   #define STRACCUM_TOOBIG  2
 16949  17007   #define SQLITE_PRINTF_INTERNAL 0x01  /* Internal-use-only converters allowed */
 16950  17008   #define SQLITE_PRINTF_SQLFUNC  0x02  /* SQL function arguments to VXPrintf */
................................................................................
 16971  17029   */
 16972  17030   struct Sqlite3Config {
 16973  17031     int bMemstat;                     /* True to enable memory status */
 16974  17032     int bCoreMutex;                   /* True to enable core mutexing */
 16975  17033     int bFullMutex;                   /* True to enable full mutexing */
 16976  17034     int bOpenUri;                     /* True to interpret filenames as URIs */
 16977  17035     int bUseCis;                      /* Use covering indices for full-scans */
        17036  +  int bSmallMalloc;                 /* Avoid large memory allocations if true */
 16978  17037     int mxStrlen;                     /* Maximum string length */
 16979  17038     int neverCorrupt;                 /* Database is always well-formed */
 16980  17039     int szLookaside;                  /* Default lookaside buffer size */
 16981  17040     int nLookaside;                   /* Default lookaside buffer count */
 16982  17041     int nStmtSpill;                   /* Stmt-journal spill-to-disk threshold */
 16983  17042     sqlite3_mem_methods m;            /* Low-level memory allocation interface */
 16984  17043     sqlite3_mutex_methods mutex;      /* Low-level mutex interface */
 16985  17044     sqlite3_pcache_methods2 pcache2;  /* Low-level page-cache interface */
 16986  17045     void *pHeap;                      /* Heap storage space */
 16987  17046     int nHeap;                        /* Size of pHeap[] */
 16988  17047     int mnReq, mxReq;                 /* Min and max heap requests sizes */
 16989  17048     sqlite3_int64 szMmap;             /* mmap() space per open file */
 16990  17049     sqlite3_int64 mxMmap;             /* Maximum value for szMmap */
 16991         -  void *pScratch;                   /* Scratch memory */
 16992         -  int szScratch;                    /* Size of each scratch buffer */
 16993         -  int nScratch;                     /* Number of scratch buffers */
 16994  17050     void *pPage;                      /* Page cache memory */
 16995  17051     int szPage;                       /* Size of each page in pPage[] */
 16996  17052     int nPage;                        /* Number of pages in pPage[] */
 16997  17053     int mxParserStack;                /* maximum depth of the parser stack */
 16998  17054     int sharedCacheEnabled;           /* true if shared-cache mode enabled */
 16999  17055     u32 szPma;                        /* Maximum Sorter PMA size */
 17000  17056     /* The above might be initialized to non-zero.  The following need to always
................................................................................
 17073  17129   SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
 17074  17130   SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
 17075  17131   SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
 17076  17132   SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
 17077  17133   SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
 17078  17134   SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
 17079  17135   SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
        17136  +SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
 17080  17137   #ifdef SQLITE_DEBUG
 17081  17138   SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
 17082  17139   #endif
 17083  17140   
 17084  17141   /*
 17085  17142   ** Return code from the parse-tree walking primitives and their
 17086  17143   ** callbacks.
................................................................................
 17225  17282   SQLITE_PRIVATE void *sqlite3Realloc(void*, u64);
 17226  17283   SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
 17227  17284   SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
 17228  17285   SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
 17229  17286   SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
 17230  17287   SQLITE_PRIVATE int sqlite3MallocSize(void*);
 17231  17288   SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
 17232         -SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
 17233         -SQLITE_PRIVATE void sqlite3ScratchFree(void*);
 17234  17289   SQLITE_PRIVATE void *sqlite3PageMalloc(int);
 17235  17290   SQLITE_PRIVATE void sqlite3PageFree(void*);
 17236  17291   SQLITE_PRIVATE void sqlite3MemSetDefault(void);
 17237  17292   #ifndef SQLITE_UNTESTABLE
 17238  17293   SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
 17239  17294   #endif
 17240  17295   SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
................................................................................
 17282  17337   # define sqlite3MemoryBarrier()
 17283  17338   #endif
 17284  17339   
 17285  17340   SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int);
 17286  17341   SQLITE_PRIVATE void sqlite3StatusUp(int, int);
 17287  17342   SQLITE_PRIVATE void sqlite3StatusDown(int, int);
 17288  17343   SQLITE_PRIVATE void sqlite3StatusHighwater(int, int);
        17344  +SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*);
 17289  17345   
 17290  17346   /* Access to mutexes used by sqlite3_status() */
 17291  17347   SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
 17292  17348   SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
 17293  17349   
 17294  17350   #ifndef SQLITE_OMIT_FLOATING_POINT
 17295  17351   SQLITE_PRIVATE   int sqlite3IsNaN(double);
................................................................................
 17718  17774   #endif
 17719  17775   
 17720  17776   SQLITE_PRIVATE const char *sqlite3ErrStr(int);
 17721  17777   SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
 17722  17778   SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
 17723  17779   SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 17724  17780   SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
        17781  +SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
        17782  +SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
 17725  17783   SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
 17726  17784   SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
 17727  17785   SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
 17728  17786   SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
 17729  17787   SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
 17730  17788   SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
 17731  17789   SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
................................................................................
 18001  18059   #define IN_INDEX_NOOP_OK     0x0001  /* OK to return IN_INDEX_NOOP */
 18002  18060   #define IN_INDEX_MEMBERSHIP  0x0002  /* IN operator used for membership test */
 18003  18061   #define IN_INDEX_LOOP        0x0004  /* IN operator used as a loop */
 18004  18062   SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
 18005  18063   
 18006  18064   SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
 18007  18065   SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
 18008         -#ifdef SQLITE_ENABLE_ATOMIC_WRITE
        18066  +#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
        18067  + || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
 18009  18068   SQLITE_PRIVATE   int sqlite3JournalCreate(sqlite3_file *);
 18010  18069   #endif
 18011  18070   
 18012  18071   SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p);
 18013  18072   SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
 18014  18073   
 18015  18074   SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
................................................................................
 18087  18146   #else
 18088  18147   # define sqlite3MemdebugSetType(X,Y)  /* no-op */
 18089  18148   # define sqlite3MemdebugHasType(X,Y)  1
 18090  18149   # define sqlite3MemdebugNoType(X,Y)   1
 18091  18150   #endif
 18092  18151   #define MEMTYPE_HEAP       0x01  /* General heap allocations */
 18093  18152   #define MEMTYPE_LOOKASIDE  0x02  /* Heap that might have been lookaside */
 18094         -#define MEMTYPE_SCRATCH    0x04  /* Scratch allocations */
 18095         -#define MEMTYPE_PCACHE     0x08  /* Page cache allocations */
        18153  +#define MEMTYPE_PCACHE     0x04  /* Page cache allocations */
 18096  18154   
 18097  18155   /*
 18098  18156   ** Threading interface
 18099  18157   */
 18100  18158   #if SQLITE_MAX_WORKER_THREADS>0
 18101  18159   SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
 18102  18160   SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**);
................................................................................
 18317  18375   */
 18318  18376   SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
 18319  18377      SQLITE_DEFAULT_MEMSTATUS,  /* bMemstat */
 18320  18378      1,                         /* bCoreMutex */
 18321  18379      SQLITE_THREADSAFE==1,      /* bFullMutex */
 18322  18380      SQLITE_USE_URI,            /* bOpenUri */
 18323  18381      SQLITE_ALLOW_COVERING_INDEX_SCAN,   /* bUseCis */
        18382  +   0,                         /* bSmallMalloc */
 18324  18383      0x7ffffffe,                /* mxStrlen */
 18325  18384      0,                         /* neverCorrupt */
 18326  18385      SQLITE_DEFAULT_LOOKASIDE,  /* szLookaside, nLookaside */
 18327  18386      SQLITE_STMTJRNL_SPILL,     /* nStmtSpill */
 18328  18387      {0,0,0,0,0,0,0,0},         /* m */
 18329  18388      {0,0,0,0,0,0,0,0,0},       /* mutex */
 18330  18389      {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
 18331  18390      (void*)0,                  /* pHeap */
 18332  18391      0,                         /* nHeap */
 18333  18392      0, 0,                      /* mnHeap, mxHeap */
 18334  18393      SQLITE_DEFAULT_MMAP_SIZE,  /* szMmap */
 18335  18394      SQLITE_MAX_MMAP_SIZE,      /* mxMmap */
 18336         -   (void*)0,                  /* pScratch */
 18337         -   0,                         /* szScratch */
 18338         -   0,                         /* nScratch */
 18339  18395      (void*)0,                  /* pPage */
 18340  18396      0,                         /* szPage */
 18341  18397      SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
 18342  18398      0,                         /* mxParserStack */
 18343  18399      0,                         /* sharedCacheEnabled */
 18344  18400      SQLITE_SORTER_PMASZ,       /* szPma */
 18345  18401      /* All the rest should always be initialized to zero */
................................................................................
 18533  18589     /* Cached OP_Column parse information is only valid if cacheStatus matches
 18534  18590     ** Vdbe.cacheCtr.  Vdbe.cacheCtr will never take on the value of
 18535  18591     ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
 18536  18592     ** the cache is out of date. */
 18537  18593     u32 cacheStatus;        /* Cache is valid if this matches Vdbe.cacheCtr */
 18538  18594     int seekResult;         /* Result of previous sqlite3BtreeMoveto() or 0
 18539  18595                             ** if there have been no prior seeks on the cursor. */
 18540         -  /* NB: seekResult does not distinguish between "no seeks have ever occurred
 18541         -  ** on this cursor" and "the most recent seek was an exact match". */
        18596  +  /* seekResult does not distinguish between "no seeks have ever occurred
        18597  +  ** on this cursor" and "the most recent seek was an exact match".
        18598  +  ** For CURTYPE_PSEUDO, seekResult is the register holding the record */
 18542  18599   
 18543  18600     /* When a new VdbeCursor is allocated, only the fields above are zeroed.
 18544  18601     ** The fields that follow are uninitialized, and must be individually
 18545  18602     ** initialized prior to first use. */
 18546  18603     VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
 18547  18604     union {
 18548         -    BtCursor *pCursor;          /* CURTYPE_BTREE.  Btree cursor */
 18549         -    sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB.   Vtab cursor */
 18550         -    int pseudoTableReg;         /* CURTYPE_PSEUDO. Reg holding content. */
 18551         -    VdbeSorter *pSorter;        /* CURTYPE_SORTER. Sorter object */
        18605  +    BtCursor *pCursor;          /* CURTYPE_BTREE or _PSEUDO.  Btree cursor */
        18606  +    sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB.              Vtab cursor */
        18607  +    VdbeSorter *pSorter;        /* CURTYPE_SORTER.            Sorter object */
 18552  18608     } uc;
 18553  18609     KeyInfo *pKeyInfo;      /* Info about index keys needed by index cursors */
 18554  18610     u32 iHdrOffset;         /* Offset to next unparsed byte of the header */
 18555  18611     Pgno pgnoRoot;          /* Root page of the open btree cursor */
 18556  18612     i16 nField;             /* Number of fields in the header */
 18557  18613     u16 nHdrParsed;         /* Number of header fields parsed so far */
 18558  18614     i64 movetoTarget;       /* Argument to the deferred sqlite3BtreeMoveto() */
................................................................................
 18626  18682   ** structures. Each Mem struct may cache multiple representations (string,
 18627  18683   ** integer etc.) of the same value.
 18628  18684   */
 18629  18685   struct sqlite3_value {
 18630  18686     union MemValue {
 18631  18687       double r;           /* Real value used when MEM_Real is set in flags */
 18632  18688       i64 i;              /* Integer value used when MEM_Int is set in flags */
 18633         -    int nZero;          /* Used when bit MEM_Zero is set in flags */
 18634         -    void *pPtr;         /* Pointer when flags=MEM_NULL and eSubtype='p' */
        18689  +    int nZero;          /* Extra zero bytes when MEM_Zero and MEM_Blob set */
        18690  +    const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
 18635  18691       FuncDef *pDef;      /* Used only when flags==MEM_Agg */
 18636  18692       RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
 18637  18693       VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
 18638  18694     } u;
 18639  18695     u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
 18640  18696     u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
 18641  18697     u8  eSubtype;       /* Subtype for this value */
................................................................................
 18659  18715   */
 18660  18716   #define MEMCELLSIZE offsetof(Mem,zMalloc)
 18661  18717   
 18662  18718   /* One or more of the following flags are set to indicate the validOK
 18663  18719   ** representations of the value stored in the Mem struct.
 18664  18720   **
 18665  18721   ** If the MEM_Null flag is set, then the value is an SQL NULL value.
 18666         -** No other flags may be set in this case.
        18722  +** For a pointer type created using sqlite3_bind_pointer() or
        18723  +** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
 18667  18724   **
 18668  18725   ** If the MEM_Str flag is set then Mem.z points at a string representation.
 18669  18726   ** Usually this is encoded in the same unicode encoding as the main
 18670  18727   ** database (see below for exceptions). If the MEM_Term flag is also
 18671  18728   ** set, then the string is nul terminated. The MEM_Int and MEM_Real 
 18672  18729   ** flags may coexist with the MEM_Str flag.
 18673  18730   */
 18674         -#define MEM_Null      0x0001   /* Value is NULL */
        18731  +#define MEM_Null      0x0001   /* Value is NULL (or a pointer) */
 18675  18732   #define MEM_Str       0x0002   /* Value is a string */
 18676  18733   #define MEM_Int       0x0004   /* Value is an integer */
 18677  18734   #define MEM_Real      0x0008   /* Value is a real number */
 18678  18735   #define MEM_Blob      0x0010   /* Value is a BLOB */
 18679  18736   #define MEM_AffMask   0x001f   /* Mask of affinity bits */
 18680  18737   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
 18681  18738   #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
 18682  18739   #define MEM_Undefined 0x0080   /* Value is undefined */
 18683  18740   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
 18684         -#define MEM_TypeMask  0x81ff   /* Mask of type bits */
        18741  +#define MEM_TypeMask  0xc1ff   /* Mask of type bits */
 18685  18742   
 18686  18743   
 18687  18744   /* Whenever Mem contains a valid string or blob representation, one of
 18688  18745   ** the following flags must be set to determine the memory management
 18689  18746   ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
 18690  18747   ** string is \000 or \u0000 terminated
 18691  18748   */
 18692         -#define MEM_Term      0x0200   /* String rep is nul terminated */
        18749  +#define MEM_Term      0x0200   /* String in Mem.z is zero terminated */
 18693  18750   #define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
 18694  18751   #define MEM_Static    0x0800   /* Mem.z points to a static string */
 18695  18752   #define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
 18696  18753   #define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
 18697  18754   #define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
 18698  18755   #define MEM_Subtype   0x8000   /* Mem.eSubtype is valid */
 18699  18756   #ifdef SQLITE_OMIT_INCRBLOB
................................................................................
 18913  18970   SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
 18914  18971   SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
 18915  18972   #ifdef SQLITE_OMIT_FLOATING_POINT
 18916  18973   # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
 18917  18974   #else
 18918  18975   SQLITE_PRIVATE   void sqlite3VdbeMemSetDouble(Mem*, double);
 18919  18976   #endif
 18920         -SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*);
        18977  +SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
 18921  18978   SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
 18922  18979   SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
 18923  18980   SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
 18924  18981   SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
 18925  18982   SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
 18926  18983   SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
 18927  18984   SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
................................................................................
 19101  19158     newValue = (sqlite3StatValueType)X;
 19102  19159     assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
 19103  19160     assert( op>=0 && op<ArraySize(statMutex) );
 19104  19161     assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
 19105  19162                                              : sqlite3MallocMutex()) );
 19106  19163     assert( op==SQLITE_STATUS_MALLOC_SIZE
 19107  19164             || op==SQLITE_STATUS_PAGECACHE_SIZE
 19108         -          || op==SQLITE_STATUS_SCRATCH_SIZE
 19109  19165             || op==SQLITE_STATUS_PARSER_STACK );
 19110  19166     if( newValue>wsdStat.mxValue[op] ){
 19111  19167       wsdStat.mxValue[op] = newValue;
 19112  19168     }
 19113  19169   }
 19114  19170   
 19115  19171   /*
................................................................................
 19149  19205     rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
 19150  19206     if( rc==0 ){
 19151  19207       *pCurrent = (int)iCur;
 19152  19208       *pHighwater = (int)iHwtr;
 19153  19209     }
 19154  19210     return rc;
 19155  19211   }
        19212  +
        19213  +/*
        19214  +** Return the number of LookasideSlot elements on the linked list
        19215  +*/
        19216  +static u32 countLookasideSlots(LookasideSlot *p){
        19217  +  u32 cnt = 0;
        19218  +  while( p ){
        19219  +    p = p->pNext;
        19220  +    cnt++;
        19221  +  }
        19222  +  return cnt;
        19223  +}
        19224  +
        19225  +/*
        19226  +** Count the number of slots of lookaside memory that are outstanding
        19227  +*/
        19228  +SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
        19229  +  u32 nInit = countLookasideSlots(db->lookaside.pInit);
        19230  +  u32 nFree = countLookasideSlots(db->lookaside.pFree);
        19231  +  if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
        19232  +  return db->lookaside.nSlot - (nInit+nFree);
        19233  +}
 19156  19234   
 19157  19235   /*
 19158  19236   ** Query status information for a single database connection
 19159  19237   */
 19160  19238   SQLITE_API int sqlite3_db_status(
 19161  19239     sqlite3 *db,          /* The database connection whose status is desired */
 19162  19240     int op,               /* Status verb */
................................................................................
 19169  19247     if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
 19170  19248       return SQLITE_MISUSE_BKPT;
 19171  19249     }
 19172  19250   #endif
 19173  19251     sqlite3_mutex_enter(db->mutex);
 19174  19252     switch( op ){
 19175  19253       case SQLITE_DBSTATUS_LOOKASIDE_USED: {
 19176         -      *pCurrent = db->lookaside.nOut;
 19177         -      *pHighwater = db->lookaside.mxOut;
        19254  +      *pCurrent = sqlite3LookasideUsed(db, pHighwater);
 19178  19255         if( resetFlag ){
 19179         -        db->lookaside.mxOut = db->lookaside.nOut;
        19256  +        LookasideSlot *p = db->lookaside.pFree;
        19257  +        if( p ){
        19258  +          while( p->pNext ) p = p->pNext;
        19259  +          p->pNext = db->lookaside.pInit;
        19260  +          db->lookaside.pInit = db->lookaside.pFree;
        19261  +          db->lookaside.pFree = 0;
        19262  +        }
 19180  19263         }
 19181  19264         break;
 19182  19265       }
 19183  19266   
 19184  19267       case SQLITE_DBSTATUS_LOOKASIDE_HIT:
 19185  19268       case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
 19186  19269       case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
................................................................................
 19719  19802     DateTime *p
 19720  19803   ){
 19721  19804     double r;
 19722  19805     if( parseYyyyMmDd(zDate,p)==0 ){
 19723  19806       return 0;
 19724  19807     }else if( parseHhMmSs(zDate, p)==0 ){
 19725  19808       return 0;
 19726         -  }else if( sqlite3StrICmp(zDate,"now")==0){
        19809  +  }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
 19727  19810       return setDateTimeToCurrent(context, p);
 19728  19811     }else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
 19729  19812       setRawDateNumber(p, r);
 19730  19813       return 0;
 19731  19814     }
 19732  19815     return 1;
 19733  19816   }
................................................................................
 20002  20085   #ifndef SQLITE_OMIT_LOCALTIME
 20003  20086       case 'l': {
 20004  20087         /*    localtime
 20005  20088         **
 20006  20089         ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
 20007  20090         ** show local time.
 20008  20091         */
 20009         -      if( sqlite3_stricmp(z, "localtime")==0 ){
        20092  +      if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
 20010  20093           computeJD(p);
 20011  20094           p->iJD += localtimeOffset(p, pCtx, &rc);
 20012  20095           clearYMD_HMS_TZ(p);
 20013  20096         }
 20014  20097         break;
 20015  20098       }
 20016  20099   #endif
................................................................................
 20028  20111             p->iJD = (sqlite3_int64)r;
 20029  20112             p->validJD = 1;
 20030  20113             p->rawS = 0;
 20031  20114             rc = 0;
 20032  20115           }
 20033  20116         }
 20034  20117   #ifndef SQLITE_OMIT_LOCALTIME
 20035         -      else if( sqlite3_stricmp(z, "utc")==0 ){
        20118  +      else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
 20036  20119           if( p->tzSet==0 ){
 20037  20120             sqlite3_int64 c1;
 20038  20121             computeJD(p);
 20039  20122             c1 = localtimeOffset(p, pCtx, &rc);
 20040  20123             if( rc==SQLITE_OK ){
 20041  20124               p->iJD -= c1;
 20042  20125               clearYMD_HMS_TZ(p);
................................................................................
 20564  20647   ** This function registered all of the above C functions as SQL
 20565  20648   ** functions.  This should be the only routine in this file with
 20566  20649   ** external linkage.
 20567  20650   */
 20568  20651   SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
 20569  20652     static FuncDef aDateTimeFuncs[] = {
 20570  20653   #ifndef SQLITE_OMIT_DATETIME_FUNCS
 20571         -    DFUNCTION(julianday,        -1, 0, 0, juliandayFunc ),
 20572         -    DFUNCTION(date,             -1, 0, 0, dateFunc      ),
 20573         -    DFUNCTION(time,             -1, 0, 0, timeFunc      ),
 20574         -    DFUNCTION(datetime,         -1, 0, 0, datetimeFunc  ),
 20575         -    DFUNCTION(strftime,         -1, 0, 0, strftimeFunc  ),
        20654  +    PURE_DATE(julianday,        -1, 0, 0, juliandayFunc ),
        20655  +    PURE_DATE(date,             -1, 0, 0, dateFunc      ),
        20656  +    PURE_DATE(time,             -1, 0, 0, timeFunc      ),
        20657  +    PURE_DATE(datetime,         -1, 0, 0, datetimeFunc  ),
        20658  +    PURE_DATE(strftime,         -1, 0, 0, strftimeFunc  ),
 20576  20659       DFUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
 20577  20660       DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
 20578  20661       DFUNCTION(current_date,      0, 0, 0, cdateFunc     ),
 20579  20662   #else
 20580  20663       STR_FUNCTION(current_time,      0, "%H:%M:%S",          0, currentTimeFunc),
 20581  20664       STR_FUNCTION(current_date,      0, "%Y-%m-%d",          0, currentTimeFunc),
 20582  20665       STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
................................................................................
 20683  20766     return id->pMethods->xWrite(id, pBuf, amt, offset);
 20684  20767   }
 20685  20768   SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
 20686  20769     return id->pMethods->xTruncate(id, size);
 20687  20770   }
 20688  20771   SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
 20689  20772     DO_OS_MALLOC_TEST(id);
 20690         -  return id->pMethods->xSync(id, flags);
        20773  +  return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
 20691  20774   }
 20692  20775   SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
 20693  20776     DO_OS_MALLOC_TEST(id);
 20694  20777     return id->pMethods->xFileSize(id, pSize);
 20695  20778   }
 20696  20779   SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
 20697  20780     DO_OS_MALLOC_TEST(id);
................................................................................
 24753  24836     ** is a no-op returning zero if SQLite is not compiled with
 24754  24837     ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
 24755  24838     UNUSED_PARAMETER(n);
 24756  24839     return 0;
 24757  24840   #endif
 24758  24841   }
 24759  24842   
 24760         -/*
 24761         -** An instance of the following object records the location of
 24762         -** each unused scratch buffer.
 24763         -*/
 24764         -typedef struct ScratchFreeslot {
 24765         -  struct ScratchFreeslot *pNext;   /* Next unused scratch buffer */
 24766         -} ScratchFreeslot;
 24767         -
 24768  24843   /*
 24769  24844   ** State information local to the memory allocation subsystem.
 24770  24845   */
 24771  24846   static SQLITE_WSD struct Mem0Global {
 24772  24847     sqlite3_mutex *mutex;         /* Mutex to serialize access */
 24773  24848     sqlite3_int64 alarmThreshold; /* The soft heap limit */
 24774  24849   
 24775         -  /*
 24776         -  ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
 24777         -  ** (so that a range test can be used to determine if an allocation
 24778         -  ** being freed came from pScratch) and a pointer to the list of
 24779         -  ** unused scratch allocations.
 24780         -  */
 24781         -  void *pScratchEnd;
 24782         -  ScratchFreeslot *pScratchFree;
 24783         -  u32 nScratchFree;
 24784         -
 24785  24850     /*
 24786  24851     ** True if heap is nearly "full" where "full" is defined by the
 24787  24852     ** sqlite3_soft_heap_limit() setting.
 24788  24853     */
 24789  24854     int nearlyFull;
 24790         -} mem0 = { 0, 0, 0, 0, 0, 0 };
        24855  +} mem0 = { 0, 0, 0 };
 24791  24856   
 24792  24857   #define mem0 GLOBAL(struct Mem0Global, mem0)
 24793  24858   
 24794  24859   /*
 24795  24860   ** Return the memory allocator mutex. sqlite3_status() needs it.
 24796  24861   */
 24797  24862   SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){
................................................................................
 24853  24918   SQLITE_PRIVATE int sqlite3MallocInit(void){
 24854  24919     int rc;
 24855  24920     if( sqlite3GlobalConfig.m.xMalloc==0 ){
 24856  24921       sqlite3MemSetDefault();
 24857  24922     }
 24858  24923     memset(&mem0, 0, sizeof(mem0));
 24859  24924     mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
 24860         -  if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
 24861         -      && sqlite3GlobalConfig.nScratch>0 ){
 24862         -    int i, n, sz;
 24863         -    ScratchFreeslot *pSlot;
 24864         -    sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
 24865         -    sqlite3GlobalConfig.szScratch = sz;
 24866         -    pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
 24867         -    n = sqlite3GlobalConfig.nScratch;
 24868         -    mem0.pScratchFree = pSlot;
 24869         -    mem0.nScratchFree = n;
 24870         -    for(i=0; i<n-1; i++){
 24871         -      pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
 24872         -      pSlot = pSlot->pNext;
 24873         -    }
 24874         -    pSlot->pNext = 0;
 24875         -    mem0.pScratchEnd = (void*)&pSlot[1];
 24876         -  }else{
 24877         -    mem0.pScratchEnd = 0;
 24878         -    sqlite3GlobalConfig.pScratch = 0;
 24879         -    sqlite3GlobalConfig.szScratch = 0;
 24880         -    sqlite3GlobalConfig.nScratch = 0;
 24881         -  }
 24882  24925     if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
 24883  24926         || sqlite3GlobalConfig.nPage<=0 ){
 24884  24927       sqlite3GlobalConfig.pPage = 0;
 24885  24928       sqlite3GlobalConfig.szPage = 0;
 24886  24929     }
 24887  24930     rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
 24888  24931     if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
................................................................................
 25025  25068   SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
 25026  25069   #ifndef SQLITE_OMIT_AUTOINIT
 25027  25070     if( sqlite3_initialize() ) return 0;
 25028  25071   #endif
 25029  25072     return sqlite3Malloc(n);
 25030  25073   }
 25031  25074   
 25032         -/*
 25033         -** Each thread may only have a single outstanding allocation from
 25034         -** xScratchMalloc().  We verify this constraint in the single-threaded
 25035         -** case by setting scratchAllocOut to 1 when an allocation
 25036         -** is outstanding clearing it when the allocation is freed.
 25037         -*/
 25038         -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
 25039         -static int scratchAllocOut = 0;
 25040         -#endif
 25041         -
 25042         -
 25043         -/*
 25044         -** Allocate memory that is to be used and released right away.
 25045         -** This routine is similar to alloca() in that it is not intended
 25046         -** for situations where the memory might be held long-term.  This
 25047         -** routine is intended to get memory to old large transient data
 25048         -** structures that would not normally fit on the stack of an
 25049         -** embedded processor.
 25050         -*/
 25051         -SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
 25052         -  void *p;
 25053         -  assert( n>0 );
 25054         -
 25055         -  sqlite3_mutex_enter(mem0.mutex);
 25056         -  sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
 25057         -  if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
 25058         -    p = mem0.pScratchFree;
 25059         -    mem0.pScratchFree = mem0.pScratchFree->pNext;
 25060         -    mem0.nScratchFree--;
 25061         -    sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
 25062         -    sqlite3_mutex_leave(mem0.mutex);
 25063         -  }else{
 25064         -    sqlite3_mutex_leave(mem0.mutex);
 25065         -    p = sqlite3Malloc(n);
 25066         -    if( sqlite3GlobalConfig.bMemstat && p ){
 25067         -      sqlite3_mutex_enter(mem0.mutex);
 25068         -      sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
 25069         -      sqlite3_mutex_leave(mem0.mutex);
 25070         -    }
 25071         -    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
 25072         -  }
 25073         -  assert( sqlite3_mutex_notheld(mem0.mutex) );
 25074         -
 25075         -
 25076         -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
 25077         -  /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
 25078         -  ** buffers per thread.
 25079         -  **
 25080         -  ** This can only be checked in single-threaded mode.
 25081         -  */
 25082         -  assert( scratchAllocOut==0 );
 25083         -  if( p ) scratchAllocOut++;
 25084         -#endif
 25085         -
 25086         -  return p;
 25087         -}
 25088         -SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
 25089         -  if( p ){
 25090         -
 25091         -#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
 25092         -    /* Verify that no more than two scratch allocation per thread
 25093         -    ** is outstanding at one time.  (This is only checked in the
 25094         -    ** single-threaded case since checking in the multi-threaded case
 25095         -    ** would be much more complicated.) */
 25096         -    assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
 25097         -    scratchAllocOut--;
 25098         -#endif
 25099         -
 25100         -    if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
 25101         -      /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
 25102         -      ScratchFreeslot *pSlot;
 25103         -      pSlot = (ScratchFreeslot*)p;
 25104         -      sqlite3_mutex_enter(mem0.mutex);
 25105         -      pSlot->pNext = mem0.pScratchFree;
 25106         -      mem0.pScratchFree = pSlot;
 25107         -      mem0.nScratchFree++;
 25108         -      assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
 25109         -      sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
 25110         -      sqlite3_mutex_leave(mem0.mutex);
 25111         -    }else{
 25112         -      /* Release memory back to the heap */
 25113         -      assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
 25114         -      assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
 25115         -      sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
 25116         -      if( sqlite3GlobalConfig.bMemstat ){
 25117         -        int iSize = sqlite3MallocSize(p);
 25118         -        sqlite3_mutex_enter(mem0.mutex);
 25119         -        sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
 25120         -        sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
 25121         -        sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
 25122         -        sqlite3GlobalConfig.m.xFree(p);
 25123         -        sqlite3_mutex_leave(mem0.mutex);
 25124         -      }else{
 25125         -        sqlite3GlobalConfig.m.xFree(p);
 25126         -      }
 25127         -    }
 25128         -  }
 25129         -}
 25130         -
 25131  25075   /*
 25132  25076   ** TRUE if p is a lookaside memory allocation from db
 25133  25077   */
 25134  25078   #ifndef SQLITE_OMIT_LOOKASIDE
 25135  25079   static int isLookaside(sqlite3 *db, void *p){
 25136  25080     return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
 25137  25081   }
................................................................................
 25214  25158         LookasideSlot *pBuf = (LookasideSlot*)p;
 25215  25159   #ifdef SQLITE_DEBUG
 25216  25160         /* Trash all content in the buffer being freed */
 25217  25161         memset(p, 0xaa, db->lookaside.sz);
 25218  25162   #endif
 25219  25163         pBuf->pNext = db->lookaside.pFree;
 25220  25164         db->lookaside.pFree = pBuf;
 25221         -      db->lookaside.nOut--;
 25222  25165         return;
 25223  25166       }
 25224  25167     }
 25225  25168     assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
 25226  25169     assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
 25227  25170     assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
 25228  25171     sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
................................................................................
 25375  25318     assert( db!=0 );
 25376  25319     assert( sqlite3_mutex_held(db->mutex) );
 25377  25320     assert( db->pnBytesFreed==0 );
 25378  25321     if( db->lookaside.bDisable==0 ){
 25379  25322       assert( db->mallocFailed==0 );
 25380  25323       if( n>db->lookaside.sz ){
 25381  25324         db->lookaside.anStat[1]++;
 25382         -    }else if( (pBuf = db->lookaside.pFree)==0 ){
 25383         -      db->lookaside.anStat[2]++;
 25384         -    }else{
        25325  +    }else if( (pBuf = db->lookaside.pFree)!=0 ){
 25385  25326         db->lookaside.pFree = pBuf->pNext;
 25386         -      db->lookaside.nOut++;
        25327  +      db->lookaside.anStat[0]++;
        25328  +      return (void*)pBuf;
        25329  +    }else if( (pBuf = db->lookaside.pInit)!=0 ){
        25330  +      db->lookaside.pInit = pBuf->pNext;
 25387  25331         db->lookaside.anStat[0]++;
 25388         -      if( db->lookaside.nOut>db->lookaside.mxOut ){
 25389         -        db->lookaside.mxOut = db->lookaside.nOut;
 25390         -      }
 25391  25332         return (void*)pBuf;
        25333  +    }else{
        25334  +      db->lookaside.anStat[2]++;
 25392  25335       }
 25393  25336     }else if( db->mallocFailed ){
 25394  25337       return 0;
 25395  25338     }
 25396  25339   #else
 25397  25340     assert( db!=0 );
 25398  25341     assert( sqlite3_mutex_held(db->mutex) );
................................................................................
 26222  26165             bufpt = "";
 26223  26166           }else if( xtype==etDYNSTRING ){
 26224  26167             zExtra = bufpt;
 26225  26168           }
 26226  26169           if( precision>=0 ){
 26227  26170             for(length=0; length<precision && bufpt[length]; length++){}
 26228  26171           }else{
 26229         -          length = sqlite3Strlen30(bufpt);
        26172  +          length = 0x7fffffff & (int)strlen(bufpt);
 26230  26173           }
 26231  26174           break;
 26232  26175         case etSQLESCAPE:           /* Escape ' characters */
 26233  26176         case etSQLESCAPE2:          /* Escape ' and enclose in '...' */
 26234  26177         case etSQLESCAPE3: {        /* Escape " characters */
 26235  26178           int i, j, k, n, isnull;
 26236  26179           int needQuote;
................................................................................
 26348  26291     if( p->mxAlloc==0 ){
 26349  26292       N = p->nAlloc - p->nChar - 1;
 26350  26293       setStrAccumError(p, STRACCUM_TOOBIG);
 26351  26294       return N;
 26352  26295     }else{
 26353  26296       char *zOld = isMalloced(p) ? p->zText : 0;
 26354  26297       i64 szNew = p->nChar;
 26355         -    assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
 26356  26298       szNew += N + 1;
 26357  26299       if( szNew+p->nChar<=p->mxAlloc ){
 26358  26300         /* Force exponential buffer size growth as long as it does not overflow,
 26359  26301         ** to avoid having to call this routine too often */
 26360  26302         szNew += p->nChar;
 26361  26303       }
 26362  26304       if( szNew > p->mxAlloc ){
................................................................................
 26390  26332   ** Append N copies of character c to the given string buffer.
 26391  26333   */
 26392  26334   SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){
 26393  26335     testcase( p->nChar + (i64)N > 0x7fffffff );
 26394  26336     if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
 26395  26337       return;
 26396  26338     }
 26397         -  assert( (p->zText==p->zBase)==!isMalloced(p) );
 26398  26339     while( (N--)>0 ) p->zText[p->nChar++] = c;
 26399  26340   }
 26400  26341   
 26401  26342   /*
 26402  26343   ** The StrAccum "p" is not large enough to accept N new bytes of z[].
 26403  26344   ** So enlarge if first, then do the append.
 26404  26345   **
................................................................................
 26408  26349   */
 26409  26350   static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
 26410  26351     N = sqlite3StrAccumEnlarge(p, N);
 26411  26352     if( N>0 ){
 26412  26353       memcpy(&p->zText[p->nChar], z, N);
 26413  26354       p->nChar += N;
 26414  26355     }
 26415         -  assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
 26416  26356   }
 26417  26357   
 26418  26358   /*
 26419  26359   ** Append N bytes of text from z to the StrAccum object.  Increase the
 26420  26360   ** size of the memory allocation for StrAccum if necessary.
 26421  26361   */
 26422  26362   SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
................................................................................
 26443  26383   
 26444  26384   /*
 26445  26385   ** Finish off a string by making sure it is zero-terminated.
 26446  26386   ** Return a pointer to the resulting string.  Return a NULL
 26447  26387   ** pointer if any kind of error was encountered.
 26448  26388   */
 26449  26389   static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
        26390  +  char *zText;
 26450  26391     assert( p->mxAlloc>0 && !isMalloced(p) );
 26451         -  p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
 26452         -  if( p->zText ){
 26453         -    memcpy(p->zText, p->zBase, p->nChar+1);
        26392  +  zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
        26393  +  if( zText ){
        26394  +    memcpy(zText, p->zText, p->nChar+1);
 26454  26395       p->printfFlags |= SQLITE_PRINTF_MALLOCED;
 26455  26396     }else{
 26456  26397       setStrAccumError(p, STRACCUM_NOMEM);
 26457  26398     }
 26458         -  return p->zText;
        26399  +  p->zText = zText;
        26400  +  return zText;
 26459  26401   }
 26460  26402   SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
 26461  26403     if( p->zText ){
 26462         -    assert( (p->zText==p->zBase)==!isMalloced(p) );
 26463  26404       p->zText[p->nChar] = 0;
 26464  26405       if( p->mxAlloc>0 && !isMalloced(p) ){
 26465  26406         return strAccumFinishRealloc(p);
 26466  26407       }
 26467  26408     }
 26468  26409     return p->zText;
 26469  26410   }
 26470  26411   
 26471  26412   /*
 26472  26413   ** Reset an StrAccum string.  Reclaim all malloced memory.
 26473  26414   */
 26474  26415   SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
 26475         -  assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
 26476  26416     if( isMalloced(p) ){
 26477  26417       sqlite3DbFree(p->db, p->zText);
 26478  26418       p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
 26479  26419     }
 26480  26420     p->zText = 0;
 26481  26421   }
 26482  26422   
................................................................................
 26491  26431   **        is malloced.
 26492  26432   ** n:     Size of zBase in bytes.  If total space requirements never exceed
 26493  26433   **        n then no memory allocations ever occur.
 26494  26434   ** mx:    Maximum number of bytes to accumulate.  If mx==0 then no memory
 26495  26435   **        allocations will ever occur.
 26496  26436   */
 26497  26437   SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
 26498         -  p->zText = p->zBase = zBase;
        26438  +  p->zText = zBase;
 26499  26439     p->db = db;
 26500         -  p->nChar = 0;
 26501  26440     p->nAlloc = n;
 26502  26441     p->mxAlloc = mx;
        26442  +  p->nChar = 0;
 26503  26443     p->accError = 0;
 26504  26444     p->printfFlags = 0;
 26505  26445   }
 26506  26446   
 26507  26447   /*
 26508  26448   ** Print into memory obtained from sqliteMalloc().  Use the internal
 26509  26449   ** %-conversion extensions.
................................................................................
 28656  28596               result = s * scale;
 28657  28597               result *= 1.0e+308;
 28658  28598             }
 28659  28599           }else{ assert( e>=342 );
 28660  28600             if( esign<0 ){
 28661  28601               result = 0.0*s;
 28662  28602             }else{
        28603  +#ifdef INFINITY
        28604  +            result = INFINITY*s;
        28605  +#else
 28663  28606               result = 1e308*1e308*s;  /* Infinity */
        28607  +#endif
 28664  28608             }
 28665  28609           }
 28666  28610         }else{
 28667  28611           /* 1.0e+22 is the largest power of 10 than can be 
 28668  28612           ** represented exactly. */
 28669  28613           while( e%22 ) { scale *= 1.0e+1; e -= 1; }
 28670  28614           while( e>0 ) { scale *= 1.0e+22; e -= 22; }
................................................................................
 28718  28662     return c;
 28719  28663   }
 28720  28664   
 28721  28665   /*
 28722  28666   ** Convert zNum to a 64-bit signed integer.  zNum must be decimal. This
 28723  28667   ** routine does *not* accept hexadecimal notation.
 28724  28668   **
 28725         -** If the zNum value is representable as a 64-bit twos-complement 
 28726         -** integer, then write that value into *pNum and return 0.
        28669  +** Returns:
 28727  28670   **
 28728         -** If zNum is exactly 9223372036854775808, return 2.  This special
 28729         -** case is broken out because while 9223372036854775808 cannot be a 
 28730         -** signed 64-bit integer, its negative -9223372036854775808 can be.
 28731         -**
 28732         -** If zNum is too big for a 64-bit integer and is not
 28733         -** 9223372036854775808  or if zNum contains any non-numeric text,
 28734         -** then return 1.
        28671  +**     0    Successful transformation.  Fits in a 64-bit signed integer.
        28672  +**     1    Excess text after the integer value
        28673  +**     2    Integer too large for a 64-bit signed integer or is malformed
        28674  +**     3    Special case of 9223372036854775808
 28735  28675   **
 28736  28676   ** length is the number of bytes in the string (bytes, not characters).
 28737  28677   ** The string is not necessarily zero-terminated.  The encoding is
 28738  28678   ** given by enc.
 28739  28679   */
 28740  28680   SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
 28741  28681     int incr;
 28742  28682     u64 u = 0;
 28743  28683     int neg = 0; /* assume positive */
 28744  28684     int i;
 28745  28685     int c = 0;
 28746  28686     int nonNum = 0;  /* True if input contains UTF16 with high byte non-zero */
        28687  +  int rc;          /* Baseline return code */
 28747  28688     const char *zStart;
 28748  28689     const char *zEnd = zNum + length;
 28749  28690     assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
 28750  28691     if( enc==SQLITE_UTF8 ){
 28751  28692       incr = 1;
 28752  28693     }else{
 28753  28694       incr = 2;
................................................................................
 28779  28720       *pNum = (i64)u;
 28780  28721     }
 28781  28722     testcase( i==18 );
 28782  28723     testcase( i==19 );
 28783  28724     testcase( i==20 );
 28784  28725     if( &zNum[i]<zEnd              /* Extra bytes at the end */
 28785  28726      || (i==0 && zStart==zNum)     /* No digits */
 28786         -   || i>19*incr                  /* Too many digits */
 28787  28727      || nonNum                     /* UTF16 with high-order bytes non-zero */
 28788  28728     ){
        28729  +    rc = 1;
        28730  +  }else{
        28731  +    rc = 0;
        28732  +  }
        28733  +  if( i>19*incr ){                /* Too many digits */
 28789  28734       /* zNum is empty or contains non-numeric text or is longer
 28790  28735       ** than 19 digits (thus guaranteeing that it is too large) */
 28791         -    return 1;
        28736  +    return 2;
 28792  28737     }else if( i<19*incr ){
 28793  28738       /* Less than 19 digits, so we know that it fits in 64 bits */
 28794  28739       assert( u<=LARGEST_INT64 );
 28795         -    return 0;
        28740  +    return rc;
 28796  28741     }else{
 28797  28742       /* zNum is a 19-digit numbers.  Compare it against 9223372036854775808. */
 28798  28743       c = compare2pow63(zNum, incr);
 28799  28744       if( c<0 ){
 28800  28745         /* zNum is less than 9223372036854775808 so it fits */
 28801  28746         assert( u<=LARGEST_INT64 );
 28802         -      return 0;
        28747  +      return rc;
 28803  28748       }else if( c>0 ){
 28804  28749         /* zNum is greater than 9223372036854775808 so it overflows */
 28805         -      return 1;
        28750  +      return 2;
 28806  28751       }else{
 28807  28752         /* zNum is exactly 9223372036854775808.  Fits if negative.  The
 28808  28753         ** special case 2 overflow if positive */
 28809  28754         assert( u-1==LARGEST_INT64 );
 28810         -      return neg ? 0 : 2;
        28755  +      return neg ? rc : 3;
 28811  28756       }
 28812  28757     }
 28813  28758   }
 28814  28759   
 28815  28760   /*
 28816  28761   ** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
 28817  28762   ** into a 64-bit signed integer.  This routine accepts hexadecimal literals,
 28818  28763   ** whereas sqlite3Atoi64() does not.
 28819  28764   **
 28820  28765   ** Returns:
 28821  28766   **
 28822  28767   **     0    Successful transformation.  Fits in a 64-bit signed integer.
 28823         -**     1    Integer too large for a 64-bit signed integer or is malformed
 28824         -**     2    Special case of 9223372036854775808
        28768  +**     1    Excess text after the integer value
        28769  +**     2    Integer too large for a 64-bit signed integer or is malformed
        28770  +**     3    Special case of 9223372036854775808
 28825  28771   */
 28826  28772   SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
 28827  28773   #ifndef SQLITE_OMIT_HEX_INTEGER
 28828  28774     if( z[0]=='0'
 28829  28775      && (z[1]=='x' || z[1]=='X')
 28830  28776     ){
 28831  28777       u64 u = 0;
 28832  28778       int i, k;
 28833  28779       for(i=2; z[i]=='0'; i++){}
 28834  28780       for(k=i; sqlite3Isxdigit(z[k]); k++){
 28835  28781         u = u*16 + sqlite3HexToInt(z[k]);
 28836  28782       }
 28837  28783       memcpy(pOut, &u, 8);
 28838         -    return (z[k]==0 && k-i<=16) ? 0 : 1;
        28784  +    return (z[k]==0 && k-i<=16) ? 0 : 2;
 28839  28785     }else
 28840  28786   #endif /* SQLITE_OMIT_HEX_INTEGER */
 28841  28787     {
 28842  28788       return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
 28843  28789     }
 28844  28790   }
 28845  28791   
................................................................................
 29441  29387   /*
 29442  29388   ** Attempt to add, substract, or multiply the 64-bit signed value iB against
 29443  29389   ** the other 64-bit signed integer at *pA and store the result in *pA.
 29444  29390   ** Return 0 on success.  Or if the operation would have resulted in an
 29445  29391   ** overflow, leave *pA unchanged and return 1.
 29446  29392   */
 29447  29393   SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
 29448         -#if GCC_VERSION>=5004000
        29394  +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
 29449  29395     return __builtin_add_overflow(*pA, iB, pA);
 29450  29396   #else
 29451  29397     i64 iA = *pA;
 29452  29398     testcase( iA==0 ); testcase( iA==1 );
 29453  29399     testcase( iB==-1 ); testcase( iB==0 );
 29454  29400     if( iB>=0 ){
 29455  29401       testcase( iA>0 && LARGEST_INT64 - iA == iB );
................................................................................
 29461  29407       if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
 29462  29408     }
 29463  29409     *pA += iB;
 29464  29410     return 0; 
 29465  29411   #endif
 29466  29412   }
 29467  29413   SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
 29468         -#if GCC_VERSION>=5004000
        29414  +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
 29469  29415     return __builtin_sub_overflow(*pA, iB, pA);
 29470  29416   #else
 29471  29417     testcase( iB==SMALLEST_INT64+1 );
 29472  29418     if( iB==SMALLEST_INT64 ){
 29473  29419       testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
 29474  29420       if( (*pA)>=0 ) return 1;
 29475  29421       *pA -= iB;
................................................................................
 29476  29422       return 0;
 29477  29423     }else{
 29478  29424       return sqlite3AddInt64(pA, -iB);
 29479  29425     }
 29480  29426   #endif
 29481  29427   }
 29482  29428   SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
 29483         -#if GCC_VERSION>=5004000
        29429  +#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
 29484  29430     return __builtin_mul_overflow(*pA, iB, pA);
 29485  29431   #else
 29486  29432     i64 iA = *pA;
 29487  29433     if( iB>0 ){
 29488  29434       if( iA>LARGEST_INT64/iB ) return 1;
 29489  29435       if( iA<SMALLEST_INT64/iB ) return 1;
 29490  29436     }else if( iB<0 ){
................................................................................
 29578  29524   SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
 29579  29525     static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
 29580  29526     LogEst y = 40;
 29581  29527     if( x<8 ){
 29582  29528       if( x<2 ) return 0;
 29583  29529       while( x<8 ){  y -= 10; x <<= 1; }
 29584  29530     }else{
        29531  +#if GCC_VERSION>=5004000
        29532  +    int i = 60 - __builtin_clzll(x);
        29533  +    y += i*10;
        29534  +    x >>= i;
        29535  +#else
 29585  29536       while( x>255 ){ y += 40; x >>= 4; }  /*OPTIMIZATION-IF-TRUE*/
 29586  29537       while( x>15 ){  y += 10; x >>= 1; }
        29538  +#endif
 29587  29539     }
 29588  29540     return a[x&7] + y - 10;
 29589  29541   }
 29590  29542   
 29591  29543   #ifndef SQLITE_OMIT_VIRTUALTABLE
 29592  29544   /*
 29593  29545   ** Convert a double into a LogEst
................................................................................
 30060  30012       /*  36 */ "Sort"             OpHelp(""),
 30061  30013       /*  37 */ "Rewind"           OpHelp(""),
 30062  30014       /*  38 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
 30063  30015       /*  39 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
 30064  30016       /*  40 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
 30065  30017       /*  41 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
 30066  30018       /*  42 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
 30067         -    /*  43 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
 30068         -    /*  44 */ "Program"          OpHelp(""),
 30069         -    /*  45 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
 30070         -    /*  46 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
 30071         -    /*  47 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
 30072         -    /*  48 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
 30073         -    /*  49 */ "IncrVacuum"       OpHelp(""),
 30074         -    /*  50 */ "VNext"            OpHelp(""),
 30075         -    /*  51 */ "Init"             OpHelp("Start at P2"),
 30076         -    /*  52 */ "Return"           OpHelp(""),
 30077         -    /*  53 */ "EndCoroutine"     OpHelp(""),
 30078         -    /*  54 */ "HaltIfNull"       OpHelp("if r[P3]=null halt"),
 30079         -    /*  55 */ "Halt"             OpHelp(""),
 30080         -    /*  56 */ "Integer"          OpHelp("r[P2]=P1"),
 30081         -    /*  57 */ "Int64"            OpHelp("r[P2]=P4"),
 30082         -    /*  58 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),
 30083         -    /*  59 */ "Null"             OpHelp("r[P2..P3]=NULL"),
 30084         -    /*  60 */ "SoftNull"         OpHelp("r[P1]=NULL"),
 30085         -    /*  61 */ "Blob"             OpHelp("r[P2]=P4 (len=P1)"),
 30086         -    /*  62 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),
 30087         -    /*  63 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),
 30088         -    /*  64 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
 30089         -    /*  65 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
 30090         -    /*  66 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),
 30091         -    /*  67 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
 30092         -    /*  68 */ "CollSeq"          OpHelp(""),
 30093         -    /*  69 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),
 30094         -    /*  70 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
 30095         -    /*  71 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
 30096         -    /*  72 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),
 30097         -    /*  73 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
 30098         -    /*  74 */ "RealAffinity"     OpHelp(""),
 30099         -    /*  75 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
 30100         -    /*  76 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
 30101         -    /*  77 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
 30102         -    /*  78 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
 30103         -    /*  79 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
 30104         -    /*  80 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
 30105         -    /*  81 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
 30106         -    /*  82 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
 30107         -    /*  83 */ "ElseNotEq"        OpHelp(""),
        30019  +    /*  43 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
        30020  +    /*  44 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
        30021  +    /*  45 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
        30022  +    /*  46 */ "Program"          OpHelp(""),
        30023  +    /*  47 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
        30024  +    /*  48 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
        30025  +    /*  49 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
        30026  +    /*  50 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
        30027  +    /*  51 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
        30028  +    /*  52 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
        30029  +    /*  53 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
        30030  +    /*  54 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
        30031  +    /*  55 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
        30032  +    /*  56 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
        30033  +    /*  57 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
        30034  +    /*  58 */ "ElseNotEq"        OpHelp(""),
        30035  +    /*  59 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
        30036  +    /*  60 */ "IncrVacuum"       OpHelp(""),
        30037  +    /*  61 */ "VNext"            OpHelp(""),
        30038  +    /*  62 */ "Init"             OpHelp("Start at P2"),
        30039  +    /*  63 */ "Return"           OpHelp(""),
        30040  +    /*  64 */ "EndCoroutine"     OpHelp(""),
        30041  +    /*  65 */ "HaltIfNull"       OpHelp("if r[P3]=null halt"),
        30042  +    /*  66 */ "Halt"             OpHelp(""),
        30043  +    /*  67 */ "Integer"          OpHelp("r[P2]=P1"),
        30044  +    /*  68 */ "Int64"            OpHelp("r[P2]=P4"),
        30045  +    /*  69 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),
        30046  +    /*  70 */ "Null"             OpHelp("r[P2..P3]=NULL"),
        30047  +    /*  71 */ "SoftNull"         OpHelp("r[P1]=NULL"),
        30048  +    /*  72 */ "Blob"             OpHelp("r[P2]=P4 (len=P1)"),
        30049  +    /*  73 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),
        30050  +    /*  74 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),
        30051  +    /*  75 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
        30052  +    /*  76 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
        30053  +    /*  77 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),
        30054  +    /*  78 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
        30055  +    /*  79 */ "CollSeq"          OpHelp(""),
        30056  +    /*  80 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
        30057  +    /*  81 */ "RealAffinity"     OpHelp(""),
        30058  +    /*  82 */ "Cast"             OpHelp("affinity(r[P1])"),
        30059  +    /*  83 */ "Permutation"      OpHelp(""),
 30108  30060       /*  84 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
 30109  30061       /*  85 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
 30110  30062       /*  86 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
 30111  30063       /*  87 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
 30112  30064       /*  88 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
 30113  30065       /*  89 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
 30114  30066       /*  90 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
 30115  30067       /*  91 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
 30116  30068       /*  92 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
 30117  30069       /*  93 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
 30118         -    /*  94 */ "Cast"             OpHelp("affinity(r[P1])"),
        30070  +    /*  94 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),
 30119  30071       /*  95 */ "BitNot"           OpHelp("r[P1]= ~r[P1]"),
 30120         -    /*  96 */ "Permutation"      OpHelp(""),
        30072  +    /*  96 */ "Column"           OpHelp("r[P3]=PX"),
 30121  30073       /*  97 */ "String8"          OpHelp("r[P2]='P4'"),
 30122         -    /*  98 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),
 30123         -    /*  99 */ "Column"           OpHelp("r[P3]=PX"),
 30124         -    /* 100 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
 30125         -    /* 101 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),
 30126         -    /* 102 */ "Count"            OpHelp("r[P2]=count()"),
 30127         -    /* 103 */ "ReadCookie"       OpHelp(""),
 30128         -    /* 104 */ "SetCookie"        OpHelp(""),
 30129         -    /* 105 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
 30130         -    /* 106 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
 30131         -    /* 107 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
 30132         -    /* 108 */ "OpenDup"          OpHelp(""),
 30133         -    /* 109 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
 30134         -    /* 110 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
 30135         -    /* 111 */ "SorterOpen"       OpHelp(""),
 30136         -    /* 112 */ "SequenceTest"     OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
 30137         -    /* 113 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
 30138         -    /* 114 */ "Close"            OpHelp(""),
 30139         -    /* 115 */ "ColumnsUsed"      OpHelp(""),
 30140         -    /* 116 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
 30141         -    /* 117 */ "NewRowid"         OpHelp("r[P2]=rowid"),
 30142         -    /* 118 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
 30143         -    /* 119 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
 30144         -    /* 120 */ "Delete"           OpHelp(""),
 30145         -    /* 121 */ "ResetCount"       OpHelp(""),
 30146         -    /* 122 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
 30147         -    /* 123 */ "SorterData"       OpHelp("r[P2]=data"),
 30148         -    /* 124 */ "RowData"          OpHelp("r[P2]=data"),
 30149         -    /* 125 */ "Rowid"            OpHelp("r[P2]=rowid"),
 30150         -    /* 126 */ "NullRow"          OpHelp(""),
 30151         -    /* 127 */ "SorterInsert"     OpHelp("key=r[P2]"),
 30152         -    /* 128 */ "IdxInsert"        OpHelp("key=r[P2]"),
 30153         -    /* 129 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
 30154         -    /* 130 */ "DeferredSeek"     OpHelp("Move P3 to P1.rowid if needed"),
 30155         -    /* 131 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
        30074  +    /*  98 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
        30075  +    /*  99 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),
        30076  +    /* 100 */ "Count"            OpHelp("r[P2]=count()"),
        30077  +    /* 101 */ "ReadCookie"       OpHelp(""),
        30078  +    /* 102 */ "SetCookie"        OpHelp(""),
        30079  +    /* 103 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
        30080  +    /* 104 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
        30081  +    /* 105 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
        30082  +    /* 106 */ "OpenDup"          OpHelp(""),
        30083  +    /* 107 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
        30084  +    /* 108 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
        30085  +    /* 109 */ "SorterOpen"       OpHelp(""),
        30086  +    /* 110 */ "SequenceTest"     OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
        30087  +    /* 111 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
        30088  +    /* 112 */ "Close"            OpHelp(""),
        30089  +    /* 113 */ "ColumnsUsed"      OpHelp(""),
        30090  +    /* 114 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
        30091  +    /* 115 */ "NewRowid"         OpHelp("r[P2]=rowid"),
        30092  +    /* 116 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
        30093  +    /* 117 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
        30094  +    /* 118 */ "Delete"           OpHelp(""),
        30095  +    /* 119 */ "ResetCount"       OpHelp(""),
        30096  +    /* 120 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
        30097  +    /* 121 */ "SorterData"       OpHelp("r[P2]=data"),
        30098  +    /* 122 */ "RowData"          OpHelp("r[P2]=data"),
        30099  +    /* 123 */ "Rowid"            OpHelp("r[P2]=rowid"),
        30100  +    /* 124 */ "NullRow"          OpHelp(""),
        30101  +    /* 125 */ "SeekEnd"          OpHelp(""),
        30102  +    /* 126 */ "SorterInsert"     OpHelp("key=r[P2]"),
        30103  +    /* 127 */ "IdxInsert"        OpHelp("key=r[P2]"),
        30104  +    /* 128 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
        30105  +    /* 129 */ "DeferredSeek"     OpHelp("Move P3 to P1.rowid if needed"),
        30106  +    /* 130 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
        30107  +    /* 131 */ "Destroy"          OpHelp(""),
 30156  30108       /* 132 */ "Real"             OpHelp("r[P2]=P4"),
 30157         -    /* 133 */ "Destroy"          OpHelp(""),
 30158         -    /* 134 */ "Clear"            OpHelp(""),
 30159         -    /* 135 */ "ResetSorter"      OpHelp(""),
 30160         -    /* 136 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
 30161         -    /* 137 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
 30162         -    /* 138 */ "SqlExec"          OpHelp(""),
 30163         -    /* 139 */ "ParseSchema"      OpHelp(""),
 30164         -    /* 140 */ "LoadAnalysis"     OpHelp(""),
 30165         -    /* 141 */ "DropTable"        OpHelp(""),
 30166         -    /* 142 */ "DropIndex"        OpHelp(""),
 30167         -    /* 143 */ "DropTrigger"      OpHelp(""),
 30168         -    /* 144 */ "IntegrityCk"      OpHelp(""),
 30169         -    /* 145 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
 30170         -    /* 146 */ "Param"            OpHelp(""),
 30171         -    /* 147 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
 30172         -    /* 148 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
 30173         -    /* 149 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
 30174         -    /* 150 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),
 30175         -    /* 151 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
 30176         -    /* 152 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
 30177         -    /* 153 */ "Expire"           OpHelp(""),
 30178         -    /* 154 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
 30179         -    /* 155 */ "VBegin"           OpHelp(""),
 30180         -    /* 156 */ "VCreate"          OpHelp(""),
 30181         -    /* 157 */ "VDestroy"         OpHelp(""),
 30182         -    /* 158 */ "VOpen"            OpHelp(""),
 30183         -    /* 159 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
 30184         -    /* 160 */ "VRename"          OpHelp(""),
 30185         -    /* 161 */ "Pagecount"        OpHelp(""),
 30186         -    /* 162 */ "MaxPgcnt"         OpHelp(""),
 30187         -    /* 163 */ "CursorHint"       OpHelp(""),
 30188         -    /* 164 */ "Noop"             OpHelp(""),
 30189         -    /* 165 */ "Explain"          OpHelp(""),
        30109  +    /* 133 */ "Clear"            OpHelp(""),
        30110  +    /* 134 */ "ResetSorter"      OpHelp(""),
        30111  +    /* 135 */ "CreateBtree"      OpHelp("r[P2]=root iDb=P1 flags=P3"),
        30112  +    /* 136 */ "SqlExec"          OpHelp(""),
        30113  +    /* 137 */ "ParseSchema"      OpHelp(""),
        30114  +    /* 138 */ "LoadAnalysis"     OpHelp(""),
        30115  +    /* 139 */ "DropTable"        OpHelp(""),
        30116  +    /* 140 */ "DropIndex"        OpHelp(""),
        30117  +    /* 141 */ "DropTrigger"      OpHelp(""),
        30118  +    /* 142 */ "IntegrityCk"      OpHelp(""),
        30119  +    /* 143 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
        30120  +    /* 144 */ "Param"            OpHelp(""),
        30121  +    /* 145 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
        30122  +    /* 146 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
        30123  +    /* 147 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
        30124  +    /* 148 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),
        30125  +    /* 149 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
        30126  +    /* 150 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
        30127  +    /* 151 */ "Expire"           OpHelp(""),
        30128  +    /* 152 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
        30129  +    /* 153 */ "VBegin"           OpHelp(""),
        30130  +    /* 154 */ "VCreate"          OpHelp(""),
        30131  +    /* 155 */ "VDestroy"         OpHelp(""),
        30132  +    /* 156 */ "VOpen"            OpHelp(""),
        30133  +    /* 157 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
        30134  +    /* 158 */ "VRename"          OpHelp(""),
        30135  +    /* 159 */ "Pagecount"        OpHelp(""),
        30136  +    /* 160 */ "MaxPgcnt"         OpHelp(""),
        30137  +    /* 161 */ "PureFunc0"        OpHelp(""),
        30138  +    /* 162 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),
        30139  +    /* 163 */ "PureFunc"         OpHelp(""),
        30140  +    /* 164 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),
        30141  +    /* 165 */ "CursorHint"       OpHelp(""),
        30142  +    /* 166 */ "Noop"             OpHelp(""),
        30143  +    /* 167 */ "Explain"          OpHelp(""),
 30190  30144     };
 30191  30145     return azName[i];
 30192  30146   }
 30193  30147   #endif
 30194  30148   
 30195  30149   /************** End of opcodes.c *********************************************/
 30196  30150   /************** Begin file os_unix.c *****************************************/
................................................................................
 30282  30236   
 30283  30237   /*
 30284  30238   ** standard include files.
 30285  30239   */
 30286  30240   #include <sys/types.h>
 30287  30241   #include <sys/stat.h>
 30288  30242   #include <fcntl.h>
        30243  +#include <sys/ioctl.h>
 30289  30244   #include <unistd.h>
 30290  30245   /* #include <time.h> */
 30291  30246   #include <sys/time.h>
 30292  30247   #include <errno.h>
 30293  30248   #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
 30294  30249   # include <sys/mman.h>
 30295  30250   #endif
 30296  30251   
 30297  30252   #if SQLITE_ENABLE_LOCKING_STYLE
 30298         -# include <sys/ioctl.h>
        30253  +/* # include <sys/ioctl.h> */
 30299  30254   # include <sys/file.h>
 30300  30255   # include <sys/param.h>
 30301  30256   #endif /* SQLITE_ENABLE_LOCKING_STYLE */
 30302  30257   
 30303  30258   #if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
 30304  30259                              (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
 30305  30260   #  if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
................................................................................
 30401  30356     sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
 30402  30357     unixInodeInfo *pInode;              /* Info about locks on this inode */
 30403  30358     int h;                              /* The file descriptor */
 30404  30359     unsigned char eFileLock;            /* The type of lock held on this fd */
 30405  30360     unsigned short int ctrlFlags;       /* Behavioral bits.  UNIXFILE_* flags */
 30406  30361     int lastErrno;                      /* The unix errno from last I/O error */
 30407  30362     void *lockingContext;               /* Locking style specific state */
 30408         -  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
        30363  +  UnixUnusedFd *pPreallocatedUnused;  /* Pre-allocated UnixUnusedFd */
 30409  30364     const char *zPath;                  /* Name of the file */
 30410  30365     unixShm *pShm;                      /* Shared memory segment information */
 30411  30366     int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
 30412  30367   #if SQLITE_MAX_MMAP_SIZE>0
 30413  30368     int nFetchOut;                      /* Number of outstanding xFetch refs */
 30414  30369     sqlite3_int64 mmapSize;             /* Usable size of mapping at pMapRegion */
 30415  30370     sqlite3_int64 mmapSizeActual;       /* Actual size of mapping at pMapRegion */
 30416  30371     sqlite3_int64 mmapSizeMax;          /* Configured FCNTL_MMAP_SIZE value */
 30417  30372     void *pMapRegion;                   /* Memory mapped region */
 30418  30373   #endif
 30419         -#ifdef __QNXNTO__
 30420  30374     int sectorSize;                     /* Device sector size */
 30421  30375     int deviceCharacteristics;          /* Precomputed device characteristics */
 30422         -#endif
 30423  30376   #if SQLITE_ENABLE_LOCKING_STYLE
 30424  30377     int openFlags;                      /* The flags specified at open() */
 30425  30378   #endif
 30426  30379   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
 30427  30380     unsigned fsFlags;                   /* cached details from statfs() */
 30428  30381   #endif
 30429  30382   #if OS_VXWORKS
................................................................................
 30717  30670   /*
 30718  30671   ** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek()
 30719  30672   ** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined.
 30720  30673   */
 30721  30674   #ifdef __ANDROID__
 30722  30675   # define lseek lseek64
 30723  30676   #endif
        30677  +
        30678  +#ifdef __linux__
        30679  +/*
        30680  +** Linux-specific IOCTL magic numbers used for controlling F2FS
        30681  +*/
        30682  +#define F2FS_IOCTL_MAGIC        0xf5
        30683  +#define F2FS_IOC_START_ATOMIC_WRITE     _IO(F2FS_IOCTL_MAGIC, 1)
        30684  +#define F2FS_IOC_COMMIT_ATOMIC_WRITE    _IO(F2FS_IOCTL_MAGIC, 2)
        30685  +#define F2FS_IOC_START_VOLATILE_WRITE   _IO(F2FS_IOCTL_MAGIC, 3)
        30686  +#define F2FS_IOC_ABORT_VOLATILE_WRITE   _IO(F2FS_IOCTL_MAGIC, 5)
        30687  +#define F2FS_IOC_GET_FEATURES           _IOR(F2FS_IOCTL_MAGIC, 12, u32)
        30688  +#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
        30689  +#endif /* __linux__ */
        30690  +
 30724  30691   
 30725  30692   /*
 30726  30693   ** Different Unix systems declare open() in different ways.  Same use
 30727  30694   ** open(const char*,int,mode_t).  Others use open(const char*,int,...).
 30728  30695   ** The difference is important when using a pointer to the function.
 30729  30696   **
 30730  30697   ** The safest way to deal with the problem is to always use this wrapper
................................................................................
 30889  30856   
 30890  30857   #if defined(HAVE_LSTAT)
 30891  30858     { "lstat",         (sqlite3_syscall_ptr)lstat,          0 },
 30892  30859   #else
 30893  30860     { "lstat",         (sqlite3_syscall_ptr)0,              0 },
 30894  30861   #endif
 30895  30862   #define osLstat      ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
        30863  +
        30864  +  { "ioctl",         (sqlite3_syscall_ptr)ioctl,          0 },
        30865  +#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
 30896  30866   
 30897  30867   }; /* End of the overrideable system calls */
 30898  30868   
 30899  30869   
 30900  30870   /*
 30901  30871   ** On some systems, calls to fchown() will trigger a message in a security
 30902  30872   ** log if they come from non-root processes.  So avoid calling fchown() if
................................................................................
 31494  31464     char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
 31495  31465   #endif
 31496  31466   };
 31497  31467   
 31498  31468   /*
 31499  31469   ** A lists of all unixInodeInfo objects.
 31500  31470   */
 31501         -static unixInodeInfo *inodeList = 0;
        31471  +static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
        31472  +static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
 31502  31473   
 31503  31474   /*
 31504  31475   **
 31505  31476   ** This function - unixLogErrorAtLine(), is only ever called via the macro
 31506  31477   ** unixLogError().
 31507  31478   **
 31508  31479   ** It is invoked after an error occurs in an OS function and errno has been
................................................................................
 31604  31575     unixInodeInfo *pInode = pFile->pInode;
 31605  31576     UnixUnusedFd *p;
 31606  31577     UnixUnusedFd *pNext;
 31607  31578     for(p=pInode->pUnused; p; p=pNext){
 31608  31579       pNext = p->pNext;
 31609  31580       robust_close(pFile, p->fd, __LINE__);
 31610  31581       sqlite3_free(p);
        31582  +    nUnusedFd--;
 31611  31583     }
 31612  31584     pInode->pUnused = 0;
 31613  31585   }
 31614  31586   
 31615  31587   /*
 31616  31588   ** Release a unixInodeInfo structure previously allocated by findInodeInfo().
 31617  31589   **
................................................................................
 31636  31608         if( pInode->pNext ){
 31637  31609           assert( pInode->pNext->pPrev==pInode );
 31638  31610           pInode->pNext->pPrev = pInode->pPrev;
 31639  31611         }
 31640  31612         sqlite3_free(pInode);
 31641  31613       }
 31642  31614     }
        31615  +  assert( inodeList!=0 || nUnusedFd==0 );
 31643  31616   }
 31644  31617   
 31645  31618   /*
 31646  31619   ** Given a file descriptor, locate the unixInodeInfo object that
 31647  31620   ** describes that file descriptor.  Create a new one if necessary.  The
 31648  31621   ** return value might be uninitialized if an error occurs.
 31649  31622   **
................................................................................
 31705  31678     memset(&fileId, 0, sizeof(fileId));
 31706  31679     fileId.dev = statbuf.st_dev;
 31707  31680   #if OS_VXWORKS
 31708  31681     fileId.pId = pFile->pId;
 31709  31682   #else
 31710  31683     fileId.ino = (u64)statbuf.st_ino;
 31711  31684   #endif
        31685  +  assert( inodeList!=0 || nUnusedFd==0 );
 31712  31686     pInode = inodeList;
 31713  31687     while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
 31714  31688       pInode = pInode->pNext;
 31715  31689     }
 31716  31690     if( pInode==0 ){
 31717  31691       pInode = sqlite3_malloc64( sizeof(*pInode) );
 31718  31692       if( pInode==0 ){
................................................................................
 32124  32098   
 32125  32099   /*
 32126  32100   ** Add the file descriptor used by file handle pFile to the corresponding
 32127  32101   ** pUnused list.
 32128  32102   */
 32129  32103   static void setPendingFd(unixFile *pFile){
 32130  32104     unixInodeInfo *pInode = pFile->pInode;
 32131         -  UnixUnusedFd *p = pFile->pUnused;
        32105  +  UnixUnusedFd *p = pFile->pPreallocatedUnused;
 32132  32106     p->pNext = pInode->pUnused;
 32133  32107     pInode->pUnused = p;
 32134  32108     pFile->h = -1;
 32135         -  pFile->pUnused = 0;
        32109  +  pFile->pPreallocatedUnused = 0;
        32110  +  nUnusedFd++;
 32136  32111   }
 32137  32112   
 32138  32113   /*
 32139  32114   ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
 32140  32115   ** must be either NO_LOCK or SHARED_LOCK.
 32141  32116   **
 32142  32117   ** If the locking level of the file descriptor is already at or below
................................................................................
 32353  32328       osUnlink(pFile->zPath);
 32354  32329       sqlite3_free(*(char**)&pFile->zPath);
 32355  32330       pFile->zPath = 0;
 32356  32331     }
 32357  32332   #endif
 32358  32333     OSTRACE(("CLOSE   %-3d\n", pFile->h));
 32359  32334     OpenCounter(-1);
 32360         -  sqlite3_free(pFile->pUnused);
        32335  +  sqlite3_free(pFile->pPreallocatedUnused);
 32361  32336     memset(pFile, 0, sizeof(unixFile));
 32362  32337     return SQLITE_OK;
 32363  32338   }
 32364  32339   
 32365  32340   /*
 32366  32341   ** Close a file.
 32367  32342   */
................................................................................
 32690  32665           rc = lrc;
 32691  32666         }
 32692  32667       }
 32693  32668     }
 32694  32669     OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
 32695  32670   
 32696  32671   #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
 32697         -  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
        32672  +  if( (rc & 0xff) == SQLITE_IOERR ){
 32698  32673       rc = SQLITE_OK;
 32699  32674       reserved=1;
 32700  32675     }
 32701  32676   #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
 32702  32677     *pResOut = reserved;
 32703  32678     return rc;
 32704  32679   }
................................................................................
 32757  32732     } else {
 32758  32733       /* got it, set the type and return ok */
 32759  32734       pFile->eFileLock = eFileLock;
 32760  32735     }
 32761  32736     OSTRACE(("LOCK    %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), 
 32762  32737              rc==SQLITE_OK ? "ok" : "failed"));
 32763  32738   #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
 32764         -  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
        32739  +  if( (rc & 0xff) == SQLITE_IOERR ){
 32765  32740       rc = SQLITE_BUSY;
 32766  32741     }
 32767  32742   #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
 32768  32743     return rc;
 32769  32744   }
 32770  32745   
 32771  32746   
................................................................................
 33294  33269           failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, 
 33295  33270                                  SHARED_SIZE, 1);
 33296  33271           if( failed && (failed2 = afpSetLock(context->dbPath, pFile, 
 33297  33272                          SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
 33298  33273             /* Can't reestablish the shared lock.  Sqlite can't deal, this is
 33299  33274             ** a critical I/O error
 33300  33275             */
 33301         -          rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : 
        33276  +          rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 : 
 33302  33277                  SQLITE_IOERR_LOCK;
 33303  33278             goto afp_end_lock;
 33304  33279           } 
 33305  33280         }else{
 33306  33281           rc = failed; 
 33307  33282         }
 33308  33283       }
................................................................................
 33574  33549     assert( id );
 33575  33550     assert( offset>=0 );
 33576  33551     assert( amt>0 );
 33577  33552   
 33578  33553     /* If this is a database file (not a journal, master-journal or temp
 33579  33554     ** file), the bytes in the locking range should never be read or written. */
 33580  33555   #if 0
 33581         -  assert( pFile->pUnused==0
        33556  +  assert( pFile->pPreallocatedUnused==0
 33582  33557          || offset>=PENDING_BYTE+512
 33583  33558          || offset+amt<=PENDING_BYTE 
 33584  33559     );
 33585  33560   #endif
 33586  33561   
 33587  33562   #if SQLITE_MAX_MMAP_SIZE>0
 33588  33563     /* Deal with as much of this read request as possible by transfering
................................................................................
 33687  33662     int wrote = 0;
 33688  33663     assert( id );
 33689  33664     assert( amt>0 );
 33690  33665   
 33691  33666     /* If this is a database file (not a journal, master-journal or temp
 33692  33667     ** file), the bytes in the locking range should never be read or written. */
 33693  33668   #if 0
 33694         -  assert( pFile->pUnused==0
        33669  +  assert( pFile->pPreallocatedUnused==0
 33695  33670          || offset>=PENDING_BYTE+512
 33696  33671          || offset+amt<=PENDING_BYTE 
 33697  33672     );
 33698  33673   #endif
 33699  33674   
 33700  33675   #ifdef SQLITE_DEBUG
 33701  33676     /* If we are doing a normal write to a database file (as opposed to
................................................................................
 34167  34142   
 34168  34143   /*
 34169  34144   ** Information and control of an open file handle.
 34170  34145   */
 34171  34146   static int unixFileControl(sqlite3_file *id, int op, void *pArg){
 34172  34147     unixFile *pFile = (unixFile*)id;
 34173  34148     switch( op ){
        34149  +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
        34150  +    case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
        34151  +      int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
        34152  +      return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
        34153  +    }
        34154  +    case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
        34155  +      int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
        34156  +      return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
        34157  +    }
        34158  +    case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
        34159  +      int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
        34160  +      return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
        34161  +    }
        34162  +#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
        34163  +
 34174  34164       case SQLITE_FCNTL_LOCKSTATE: {
 34175  34165         *(int*)pArg = pFile->eFileLock;
 34176  34166         return SQLITE_OK;
 34177  34167       }
 34178  34168       case SQLITE_FCNTL_LAST_ERRNO: {
 34179  34169         *(int*)pArg = pFile->lastErrno;
 34180  34170         return SQLITE_OK;
................................................................................
 34217  34207   #if SQLITE_MAX_MMAP_SIZE>0
 34218  34208       case SQLITE_FCNTL_MMAP_SIZE: {
 34219  34209         i64 newLimit = *(i64*)pArg;
 34220  34210         int rc = SQLITE_OK;
 34221  34211         if( newLimit>sqlite3GlobalConfig.mxMmap ){
 34222  34212           newLimit = sqlite3GlobalConfig.mxMmap;
 34223  34213         }
        34214  +
        34215  +      /* The value of newLimit may be eventually cast to (size_t) and passed
        34216  +      ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a
        34217  +      ** 64-bit type. */
        34218  +      if( newLimit>0 && sizeof(size_t)<8 ){
        34219  +        newLimit = (newLimit & 0x7FFFFFFF);
        34220  +      }
        34221  +
 34224  34222         *(i64*)pArg = pFile->mmapSizeMax;
 34225  34223         if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
 34226  34224           pFile->mmapSizeMax = newLimit;
 34227  34225           if( pFile->mmapSize>0 ){
 34228  34226             unixUnmapfile(pFile);
 34229  34227             rc = unixMapfile(pFile, -1);
 34230  34228           }
................................................................................
 34250  34248       }
 34251  34249   #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
 34252  34250     }
 34253  34251     return SQLITE_NOTFOUND;
 34254  34252   }
 34255  34253   
 34256  34254   /*
 34257         -** Return the sector size in bytes of the underlying block device for
 34258         -** the specified file. This is almost always 512 bytes, but may be
 34259         -** larger for some devices.
 34260         -**
 34261         -** SQLite code assumes this function cannot fail. It also assumes that
 34262         -** if two files are created in the same file-system directory (i.e.
 34263         -** a database and its journal file) that the sector size will be the
 34264         -** same for both.
 34265         -*/
 34266         -#ifndef __QNXNTO__ 
 34267         -static int unixSectorSize(sqlite3_file *NotUsed){
 34268         -  UNUSED_PARAMETER(NotUsed);
 34269         -  return SQLITE_DEFAULT_SECTOR_SIZE;
 34270         -}
 34271         -#endif
 34272         -
 34273         -/*
 34274         -** The following version of unixSectorSize() is optimized for QNX.
 34275         -*/
 34276         -#ifdef __QNXNTO__
        34255  +** If pFd->sectorSize is non-zero when this function is called, it is a
        34256  +** no-op. Otherwise, the values of pFd->sectorSize and 
        34257  +** pFd->deviceCharacteristics are set according to the file-system 
        34258  +** characteristics. 
        34259  +**
        34260  +** There are two versions of this function. One for QNX and one for all
        34261  +** other systems.
        34262  +*/
        34263  +#ifndef __QNXNTO__
        34264  +static void setDeviceCharacteristics(unixFile *pFd){
        34265  +  assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
        34266  +  if( pFd->sectorSize==0 ){
        34267  +#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
        34268  +    int res;
        34269  +    u32 f = 0;
        34270  +
        34271  +    /* Check for support for F2FS atomic batch writes. */
        34272  +    res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
        34273  +    if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
        34274  +      pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
        34275  +    }
        34276  +#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
        34277  +
        34278  +    /* Set the POWERSAFE_OVERWRITE flag if requested. */
        34279  +    if( pFd->ctrlFlags & UNIXFILE_PSOW ){
        34280  +      pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
        34281  +    }
        34282  +
        34283  +    pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
        34284  +  }
        34285  +}
        34286  +#else
 34277  34287   #include <sys/dcmd_blk.h>
 34278  34288   #include <sys/statvfs.h>
 34279         -static int unixSectorSize(sqlite3_file *id){
 34280         -  unixFile *pFile = (unixFile*)id;
        34289  +static void setDeviceCharacteristics(unixFile *pFile){
 34281  34290     if( pFile->sectorSize == 0 ){
 34282  34291       struct statvfs fsInfo;
 34283  34292          
 34284  34293       /* Set defaults for non-supported filesystems */
 34285  34294       pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
 34286  34295       pFile->deviceCharacteristics = 0;
 34287  34296       if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
................................................................................
 34342  34351     }
 34343  34352     /* Last chance verification.  If the sector size isn't a multiple of 512
 34344  34353     ** then it isn't valid.*/
 34345  34354     if( pFile->sectorSize % 512 != 0 ){
 34346  34355       pFile->deviceCharacteristics = 0;
 34347  34356       pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
 34348  34357     }
 34349         -  return pFile->sectorSize;
 34350  34358   }
 34351         -#endif /* __QNXNTO__ */
        34359  +#endif
        34360  +
        34361  +/*
        34362  +** Return the sector size in bytes of the underlying block device for
        34363  +** the specified file. This is almost always 512 bytes, but may be
        34364  +** larger for some devices.
        34365  +**
        34366  +** SQLite code assumes this function cannot fail. It also assumes that
        34367  +** if two files are created in the same file-system directory (i.e.
        34368  +** a database and its journal file) that the sector size will be the
        34369  +** same for both.
        34370  +*/
        34371  +static int unixSectorSize(sqlite3_file *id){
        34372  +  unixFile *pFd = (unixFile*)id;
        34373  +  setDeviceCharacteristics(pFd);
        34374  +  return pFd->sectorSize;
        34375  +}
 34352  34376   
 34353  34377   /*
 34354  34378   ** Return the device characteristics for the file.
 34355  34379   **
 34356  34380   ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
 34357  34381   ** However, that choice is controversial since technically the underlying
 34358  34382   ** file system does not always provide powersafe overwrites.  (In other
................................................................................
 34360  34384   ** written might end up being altered.)  However, non-PSOW behavior is very,
 34361  34385   ** very rare.  And asserting PSOW makes a large reduction in the amount
 34362  34386   ** of required I/O for journaling, since a lot of padding is eliminated.
 34363  34387   **  Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
 34364  34388   ** available to turn it off and URI query parameter available to turn it off.
 34365  34389   */
 34366  34390   static int unixDeviceCharacteristics(sqlite3_file *id){
 34367         -  unixFile *p = (unixFile*)id;
 34368         -  int rc = 0;
 34369         -#ifdef __QNXNTO__
 34370         -  if( p->sectorSize==0 ) unixSectorSize(id);
 34371         -  rc = p->deviceCharacteristics;
 34372         -#endif
 34373         -  if( p->ctrlFlags & UNIXFILE_PSOW ){
 34374         -    rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
 34375         -  }
 34376         -  return rc;
        34391  +  unixFile *pFd = (unixFile*)id;
        34392  +  setDeviceCharacteristics(pFd);
        34393  +  return pFd->deviceCharacteristics;
 34377  34394   }
 34378  34395   
 34379  34396   #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
 34380  34397   
 34381  34398   /*
 34382  34399   ** Return the system page size.
 34383  34400   **
................................................................................
 35627  35644   ){
 35628  35645     const sqlite3_io_methods *pLockingStyle;
 35629  35646     unixFile *pNew = (unixFile *)pId;
 35630  35647     int rc = SQLITE_OK;
 35631  35648   
 35632  35649     assert( pNew->pInode==NULL );
 35633  35650   
 35634         -  /* Usually the path zFilename should not be a relative pathname. The
 35635         -  ** exception is when opening the proxy "conch" file in builds that
 35636         -  ** include the special Apple locking styles.
 35637         -  */
 35638         -#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
 35639         -  assert( zFilename==0 || zFilename[0]=='/' 
 35640         -    || pVfs->pAppData==(void*)&autolockIoFinder );
 35641         -#else
 35642         -  assert( zFilename==0 || zFilename[0]=='/' );
 35643         -#endif
 35644         -
 35645  35651     /* No locking occurs in temporary files */
 35646  35652     assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
 35647  35653   
 35648  35654     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
 35649  35655     pNew->h = h;
 35650  35656     pNew->pVfs = pVfs;
 35651  35657     pNew->zPath = zFilename;
................................................................................
 35895  35901     /* Do not search for an unused file descriptor on vxworks. Not because
 35896  35902     ** vxworks would not benefit from the change (it might, we're not sure),
 35897  35903     ** but because no way to test it is currently available. It is better 
 35898  35904     ** not to risk breaking vxworks support for the sake of such an obscure 
 35899  35905     ** feature.  */
 35900  35906   #if !OS_VXWORKS
 35901  35907     struct stat sStat;                   /* Results of stat() call */
        35908  +
        35909  +  unixEnterMutex();
 35902  35910   
 35903  35911     /* A stat() call may fail for various reasons. If this happens, it is
 35904  35912     ** almost certain that an open() call on the same path will also fail.
 35905  35913     ** For this reason, if an error occurs in the stat() call here, it is
 35906  35914     ** ignored and -1 is returned. The caller will try to open a new file
 35907  35915     ** descriptor on the same path, fail, and return an error to SQLite.
 35908  35916     **
 35909  35917     ** Even if a subsequent open() call does succeed, the consequences of
 35910  35918     ** not searching for a reusable file descriptor are not dire.  */
 35911         -  if( 0==osStat(zPath, &sStat) ){
        35919  +  if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
 35912  35920       unixInodeInfo *pInode;
 35913  35921   
 35914         -    unixEnterMutex();
 35915  35922       pInode = inodeList;
 35916  35923       while( pInode && (pInode->fileId.dev!=sStat.st_dev
 35917  35924                        || pInode->fileId.ino!=(u64)sStat.st_ino) ){
 35918  35925          pInode = pInode->pNext;
 35919  35926       }
 35920  35927       if( pInode ){
 35921  35928  <