Fossil

Check-in Differences
Login

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

Difference From:

[0ef9501c] Check for the presence of BIO_ADDR_hostname_string before using it. (user: andybradford tags: trunk, date: 2019-03-25 14:02:50)

To:

[f8d7f76b] Version 2.8 (user: drh tags: trunk, release, version-2.8, date: 2019-02-20 15:01:32)

Changes to Makefile.osx-jaguar.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
BCC = cc
BCCFLAGS = $(CFLAGS)

#### The suffix to add to final executable file.  When cross-compiling
#    to windows, make this ".exe".  Otherwise leave it blank.
#
E =

TCC = cc
TCCFLAGS = $(CFLAGS)

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
................................................................................
TCC += -DSQLITE_WITHOUT_ZONEMALLOC
TCC += -D_BSD_SOURCE=1
TCC += -DWITHOUT_ICONV
TCC += -Dsocklen_t=int
TCC += -DSQLITE_MAX_MMAP_SIZE=0
TCC += -DFOSSIL_ENABLE_LEGACY_MV_RM=1
INSTALLDIR = $(DESTDIR)/usr/local/bin
USE_SYSTEM_SQLITE =
USE_LINENOISE = 1
# FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@
FOSSIL_ENABLE_TCL = 0
FOSSIL_ENABLE_MINIZ = 0

include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile







|







 







|









36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#
BCC = cc
BCCFLAGS = $(CFLAGS)

#### The suffix to add to final executable file.  When cross-compiling
#    to windows, make this ".exe".  Otherwise leave it blank.
#
E = 

TCC = cc
TCCFLAGS = $(CFLAGS)

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
................................................................................
TCC += -DSQLITE_WITHOUT_ZONEMALLOC
TCC += -D_BSD_SOURCE=1
TCC += -DWITHOUT_ICONV
TCC += -Dsocklen_t=int
TCC += -DSQLITE_MAX_MMAP_SIZE=0
TCC += -DFOSSIL_ENABLE_LEGACY_MV_RM=1
INSTALLDIR = $(DESTDIR)/usr/local/bin
USE_SYSTEM_SQLITE = 
USE_LINENOISE = 1
# FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@
FOSSIL_ENABLE_TCL = 0
FOSSIL_ENABLE_MINIZ = 0

include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile

Deleted README.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# About Fossil

Fossil is a distributed version control system that has been widely
used since 2007.  Fossil was originally designed to support the
[SQLite](https://sqlite.org) project but has been adopted by many other
projects as well.

Fossil is self-hosting at <https://fossil-scm.org>.

If you are reading this on GitHub, then you are looking at a Git mirror
of the self-hosting Fossil repository.  The purpose of that mirror is to
test and exercise Fossil's ability to export a Git mirror.  Nobody much
uses the GitHub mirror, except to verify that the mirror logic works.  If
you want to know more about Fossil, visit the official self-hosting site
linked above.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Changes to VERSION.

1
2.9
|
1
2.8

Changes to auto.def.

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    # search for the system SQLite once with -ldl, and once without. If
    # the library can only be found with $extralibs set to -ldl, then
    # the code below will append -ldl to LIBS.
    #
    foreach extralibs {{} {-ldl}} {

      # Locate the system SQLite by searching for sqlite3_open(). Then check
      # if sqlite3_stmt_isexplain can be found as well. If we can find open() but
      # not stmt_isexplain(), then the system SQLite is too old to link against
      # fossil.
      #
      if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} {
        if {![check-function-in-lib sqlite3_stmt_isexplain sqlite3 $extralibs]} {
          user-error "system sqlite3 too old (require >= 3.28.0)"
        }

        # Success. Update symbols and return.
        #
        define USE_SYSTEM_SQLITE 1
        define-append LIBS -lsqlite3
        define-append LIBS $extralibs
................................................................................

        # Silence OpenSSL deprecation warnings on Mac OS X 10.7.
        if {[string match *-darwin* [get-define host]]} {
            if {[cctest -cflags {-Wdeprecated-declarations}]} {
                define-append EXTRA_CFLAGS -Wdeprecated-declarations
            }
        }
        if {[cc-check-function-in-lib BIO_ADDR_hostname_string ssl]} {
            define HAVE_BIO_ADDR_HS 1
            msg-result "Using BIO_ADDR_hostname_string"
        }
    } else {
        user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
    }
} else {
    if {[info exists ::zlib_lib]} {
        define-append LIBS $::zlib_lib
    }







|
|



|
|







 







<
<
<
<







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
374
375
376
377
378
379
380




381
382
383
384
385
386
387
    # search for the system SQLite once with -ldl, and once without. If
    # the library can only be found with $extralibs set to -ldl, then
    # the code below will append -ldl to LIBS.
    #
    foreach extralibs {{} {-ldl}} {

      # Locate the system SQLite by searching for sqlite3_open(). Then check
      # if sqlite3_create_window_function can be found as well. If we can find open() but
      # not create_window_function(), then the system SQLite is too old to link against
      # fossil.
      #
      if {[check-function-in-lib sqlite3_open sqlite3 $extralibs]} {
        if {![check-function-in-lib sqlite3_create_window_function sqlite3 $extralibs]} {
          user-error "system sqlite3 too old (require >= 3.25.0)"
        }

        # Success. Update symbols and return.
        #
        define USE_SYSTEM_SQLITE 1
        define-append LIBS -lsqlite3
        define-append LIBS $extralibs
................................................................................

        # Silence OpenSSL deprecation warnings on Mac OS X 10.7.
        if {[string match *-darwin* [get-define host]]} {
            if {[cctest -cflags {-Wdeprecated-declarations}]} {
                define-append EXTRA_CFLAGS -Wdeprecated-declarations
            }
        }




    } else {
        user-error "OpenSSL not found. Consider --with-openssl=none to disable HTTPS support"
    }
} else {
    if {[info exists ::zlib_lib]} {
        define-append LIBS $::zlib_lib
    }

Changes to skins/enhanced1/header.txt.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    set logourl [getLogoUrl $baseurl]
    </th1>
    <a href="$logourl">
      <img src="$logo_image_url" border="0" alt="$project_name">
    </a>
  </div>
  <div class="title">$<title></div>
  <div class="status"><nobr><th1>
     if {[info exists login]} {
       puts "Logged in as $login"
     } else {
       puts "Not logged in"
     }
  </th1></nobr><small><div id="clock"></div></small></div>
</div>







|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    set logourl [getLogoUrl $baseurl]
    </th1>
    <a href="$logourl">
      <img src="$logo_image_url" border="0" alt="$project_name">
    </a>
  </div>
  <div class="title">$<title></div>
  <div class="status"><th1>
     if {[info exists login]} {
       puts "Logged in as $login"
     } else {
       puts "Not logged in"
     }
  </th1></nobr><small><div id="clock"></div></small></div>
</div>

Changes to src/backoffice.c.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633
634
635
636
637
638
639
640
# include <unistd.h>
# include <sys/types.h>
# include <signal.h>
# include <errno.h>
# include <fcntl.h>
# define GETPID getpid
#endif
#include <time.h>

/*
** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
** processing run is valid.  Each backoffice run monopolizes the lease for
** at least this amount of time.  Hopefully all backoffice processing is
** finished much faster than this - usually in less than a second.  But
** regardless of how long each invocation lasts, successive backoffice runs
................................................................................
     && x.idNext!=idSelf
     && backofficeProcessExists(x.idNext)
    ){
      /* Another backoffice process is already queued up to run.  This
      ** process does not need to do any backoffice work and can stop
      ** immediately. */
      db_end_transaction(0);
      backofficeTrace("/***** Backoffice Processing Not Needed In %d *****/\n",
                      GETPID());
      break;
    }
    if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
      /* This process can start doing backoffice work immediately */
      x.idCurrent = idSelf;
      x.tmCurrent = tmNow + BKOFCE_LEASE_TIME;
      x.idNext = 0;
................................................................................
      break;
    }
    if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
      /* If the no-delay flag is set, exit immediately rather than queuing
      ** up.  Assume that some future request will come along and handle any
      ** necessary backoffice work. */
      db_end_transaction(0);
      backofficeTrace(
           "/***** Backoffice No-Delay Exit For %d *****/\n",
           GETPID());
      break;
    }
    /* This process needs to queue up and wait for the current lease
    ** to expire before continuing. */
    x.idNext = idSelf;
    x.tmNext = (tmNow>x.tmCurrent ? tmNow : x.tmCurrent) + BKOFCE_LEASE_TIME;
    backofficeWriteLease(&x);
................................................................................
  alert_backoffice(0);
  smtp_cleanup();
}

/*
** COMMAND: backoffice*
**
** Usage: backoffice [OPTIONS...] [REPOSITORIES...]
**
** Run backoffice processing on the repositories listed.  If no
** repository is specified, run it on the repository of the local checkout.
**
** This might be done by a cron job or similar to make sure backoffice
** processing happens periodically.  Or, the --poll option can be used
** to run this command as a daemon that will periodically invoke backoffice
** on collection of repositories.
**
** OPTIONS:
**
**    --debug                 Show what this command is doing.
**
**    --nodelay               Do not queue up or wait for a backoffice job
**                            to complete. If no work is available or if
**                            backoffice has run recently, return immediately.
**                            The --nodelay option is implied if more than
**                            one repository is listed on the command-line.
**
**    --poll N                Repeat backoffice calls for repositories that
**                            change in appoximately N-second intervals.
**                            N less than 1 turns polling off (the default).
**
**    --trace                 Enable debugging output on stderr
*/
void backoffice_command(void){
  int nPoll;
  const char *zPoll;
  int bDebug = 0;
  unsigned int nCmd = 0;
  if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;
  if( find_option("nodelay",0,0)!=0 ) backofficeNoDelay = 1;
  zPoll = find_option("poll",0,1);
  nPoll = zPoll ? atoi(zPoll) : 0;
  bDebug = find_option("debug",0,0)!=0;

  /* Silently consume the -R or --repository flag, leaving behind its
  ** argument. This is for legacy compatibility. Older versions of the
  ** backoffice command only ran on a single repository that was specified
  ** using the -R option. */
  (void)find_option("repository","R",0);

  verify_all_options();
  if( g.argc>3 || nPoll>0 ){
    /* Either there are multiple repositories named on the command-line
    ** or we are polling.  In either case, each backoffice should be run
    ** using a separate sub-process */
    int i;
    time_t iNow = 0;
    time_t ix;
    while( 1 /* exit via "break;" */){
      time_t iNext = time(0);
      for(i=2; i<g.argc; i++){
        Blob cmd;
        if( !file_isfile(g.argv[i], ExtFILE) ) continue;
        if( iNow && iNow>file_mtime(g.argv[i],ExtFILE) ) continue;
        blob_init(&cmd, 0, 0);
        blob_append_escaped_arg(&cmd, g.nameOfExe);
        blob_append(&cmd, " backoffice --nodelay", -1);
        if( g.fAnyTrace ){
          blob_append(&cmd, " --trace", -1);
        }
        blob_append_escaped_arg(&cmd, g.argv[i]);
        nCmd++;
        if( bDebug ){
          fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd));
        }
        fossil_system(blob_str(&cmd));
        blob_reset(&cmd);
      }
      if( nPoll<1 ) break;
      iNow = iNext;
      ix = time(0);
      if( ix < iNow+nPoll ){
        sqlite3_int64 nMS = (iNow + nPoll - ix)*1000;
        if( bDebug )fossil_print("SLEEP: %lld\n", nMS);
        sqlite3_sleep((int)nMS);
      }
    }
  }else{
    if( g.argc==3 ){
      g.zRepositoryOption = g.argv[2];
      g.argc--;
    }
    db_find_and_open_repository(0,0);

    backoffice_thread();
  }
}

/*
** This is the main interface to backoffice from the rest of the system.
** This routine launches either backoffice_thread() directly or as a
** subprocess.
*/







<







 







<
<







 







<
<
<







 







|

<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
|
<







78
79
80
81
82
83
84

85
86
87
88
89
90
91
...
452
453
454
455
456
457
458


459
460
461
462
463
464
465
...
472
473
474
475
476
477
478



479
480
481
482
483
484
485
...
533
534
535
536
537
538
539
540
541



542
543


















544
545




546





















































547
548
549

550
551
552
553
554
555
556
# include <unistd.h>
# include <sys/types.h>
# include <signal.h>
# include <errno.h>
# include <fcntl.h>
# define GETPID getpid
#endif


/*
** The BKOFCE_LEASE_TIME is the amount of time for which a single backoffice
** processing run is valid.  Each backoffice run monopolizes the lease for
** at least this amount of time.  Hopefully all backoffice processing is
** finished much faster than this - usually in less than a second.  But
** regardless of how long each invocation lasts, successive backoffice runs
................................................................................
     && x.idNext!=idSelf
     && backofficeProcessExists(x.idNext)
    ){
      /* Another backoffice process is already queued up to run.  This
      ** process does not need to do any backoffice work and can stop
      ** immediately. */
      db_end_transaction(0);


      break;
    }
    if( x.tmCurrent<tmNow && backofficeProcessDone(x.idCurrent) ){
      /* This process can start doing backoffice work immediately */
      x.idCurrent = idSelf;
      x.tmCurrent = tmNow + BKOFCE_LEASE_TIME;
      x.idNext = 0;
................................................................................
      break;
    }
    if( backofficeNoDelay || db_get_boolean("backoffice-nodelay",0) ){
      /* If the no-delay flag is set, exit immediately rather than queuing
      ** up.  Assume that some future request will come along and handle any
      ** necessary backoffice work. */
      db_end_transaction(0);



      break;
    }
    /* This process needs to queue up and wait for the current lease
    ** to expire before continuing. */
    x.idNext = idSelf;
    x.tmNext = (tmNow>x.tmCurrent ? tmNow : x.tmCurrent) + BKOFCE_LEASE_TIME;
    backofficeWriteLease(&x);
................................................................................
  alert_backoffice(0);
  smtp_cleanup();
}

/*
** COMMAND: backoffice*
**
** Usage: backoffice [-R repository]
**



** Run backoffice processing.  This might be done by a cron job or
** similar to make sure backoffice processing happens periodically.


















*/
void backoffice_command(void){




  if( find_option("trace",0,0)!=0 ) g.fAnyTrace = 1;





















































  db_find_and_open_repository(0,0);
  verify_all_options();
  backoffice_thread();

}

/*
** This is the main interface to backoffice from the rest of the system.
** This routine launches either backoffice_thread() directly or as a
** subprocess.
*/

Changes to src/capabilities.c.

364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
    "   FROM t LEFT JOIN user ON t.id=user.login"
    " UNION ALL"
    " SELECT 'New User Default', fullcap(%Q), 10, 1"
    " UNION ALL"
    " SELECT 'Regular User', fullcap(capunion(cap)), 20, count(*) FROM user"
    " WHERE cap NOT GLOB '*[as]*'"
    " UNION ALL"
    " SELECT 'Adminstrator', fullcap(capunion(cap)), 30, count(*) FROM user"
    " WHERE cap GLOB '*[as]*'"
    " ORDER BY 3 ASC",
    db_get("default-perms","")
  );
  @ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1">
  @ <tr><th>&nbsp;<th>Code<th>Forum<th>Tickets<th>Wiki\
  @ <th>Unversioned Content</th></tr>







|







364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
    "   FROM t LEFT JOIN user ON t.id=user.login"
    " UNION ALL"
    " SELECT 'New User Default', fullcap(%Q), 10, 1"
    " UNION ALL"
    " SELECT 'Regular User', fullcap(capunion(cap)), 20, count(*) FROM user"
    " WHERE cap NOT GLOB '*[as]*'"
    " UNION ALL"
    " SELECT 'Adminstator', fullcap(capunion(cap)), 30, count(*) FROM user"
    " WHERE cap GLOB '*[as]*'"
    " ORDER BY 3 ASC",
    db_get("default-perms","")
  );
  @ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1">
  @ <tr><th>&nbsp;<th>Code<th>Forum<th>Tickets<th>Wiki\
  @ <th>Unversioned Content</th></tr>

Changes to src/checkout.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86


87
88
89
90
91
92
93
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  return db_exists("SELECT 1 FROM vfile WHERE chnged"
                   " OR coalesce(origname!=pathname,0)");
}

/*
** Undo the current check-out.  Unlink all files from the disk.
** Clear the VFILE table.
**
** Also delete any directory that becomes empty as a result of deleting
** files due to this operation, as long as that directory is not the
** current working directory and is not on the empty-dirs list.
*/
void uncheckout(int vid){
  char *zPwd;
  if( vid<=0 ) return;
  sqlite3_create_function(g.db, "dirname",1,SQLITE_UTF8,0,
                          file_dirname_sql_function, 0, 0);
  sqlite3_create_function(g.db, "unlink",1,SQLITE_UTF8,0,
                          file_delete_sql_function, 0, 0);
  sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
                          file_rmdir_sql_function, 0, 0);
  db_multi_exec(
    "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
    filename_collation()
  );
  db_multi_exec(
    "INSERT OR IGNORE INTO dir_to_delete(name)"
    "  SELECT dirname(pathname) FROM vfile"
    "   WHERE vid=%d AND mrid>0",
    vid
  );
  do{
    db_multi_exec(
      "INSERT OR IGNORE INTO dir_to_delete(name)"
      " SELECT dirname(name) FROM dir_to_delete;"
    );
  }while( db_changes() );
  db_multi_exec(
    "SELECT unlink(%Q||pathname) FROM vfile"
    " WHERE vid=%d AND mrid>0;",
    g.zLocalRoot, vid
  );
  ensure_empty_dirs_created(1);
  zPwd = file_getcwd(0,0);
  db_multi_exec(
    "SELECT rmdir(%Q||name) FROM dir_to_delete"
    " WHERE (%Q||name)<>%Q ORDER BY name DESC",
    g.zLocalRoot, g.zLocalRoot, zPwd
  );
  fossil_free(zPwd);


  db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
}


/*
** Given the abbreviated UUID name of a version, load the content of that
** version in the VFILE table.  Return the VID for the version.
................................................................................
  }
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
  if( !keepFlag ){
    vfile_to_disk(vid, 0, !g.fQuiet, promptFlag);
  }
  checkout_set_all_exe(vid);
  manifest_to_disk(vid);
  ensure_empty_dirs_created(0);
  db_set_checkout(vid);
  undo_reset();
  db_multi_exec("DELETE FROM vmerge");
  if( !keepFlag && db_get_boolean("repo-cksum",1) ){
    vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
    vfile_aggregate_checksum_disk(vid, &cksum2);
    if( blob_compare(&cksum1, &cksum2) ){







<
<
<
<


<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>







 







|







37
38
39
40
41
42
43




44
45

46



































47
48
49
50
51
52
53
54
55
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  return db_exists("SELECT 1 FROM vfile WHERE chnged"
                   " OR coalesce(origname!=pathname,0)");
}

/*
** Undo the current check-out.  Unlink all files from the disk.
** Clear the VFILE table.




*/
void uncheckout(int vid){

  if( vid>0 ){



































    vfile_unlink(vid);
  }
  db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
}


/*
** Given the abbreviated UUID name of a version, load the content of that
** version in the VFILE table.  Return the VID for the version.
................................................................................
  }
  db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid);
  if( !keepFlag ){
    vfile_to_disk(vid, 0, !g.fQuiet, promptFlag);
  }
  checkout_set_all_exe(vid);
  manifest_to_disk(vid);
  ensure_empty_dirs_created();
  db_set_checkout(vid);
  undo_reset();
  db_multi_exec("DELETE FROM vmerge");
  if( !keepFlag && db_get_boolean("repo-cksum",1) ){
    vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
    vfile_aggregate_checksum_disk(vid, &cksum2);
    if( blob_compare(&cksum1, &cksum2) ){

Changes to src/db.c.

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
    va_start(ap, zFormat);
    rc = db_vprepare(pStmt, DB_PREPARE_PERSISTENT, zFormat, ap);
    va_end(ap);
  }
  return rc;
}

/* Return TRUE if static Stmt object pStmt has been initialized.
*/
int db_static_stmt_is_init(Stmt *pStmt){
  return blob_size(&pStmt->sql)>0;
}

/* Prepare a statement using text placed inside a Blob
** using blob_append_sql().
*/
int db_prepare_blob(Stmt *pStmt, Blob *pSql){
  int rc;
  char *zSql;
  pStmt->sql = *pSql;







<
<
<
<
<
<







360
361
362
363
364
365
366






367
368
369
370
371
372
373
    va_start(ap, zFormat);
    rc = db_vprepare(pStmt, DB_PREPARE_PERSISTENT, zFormat, ap);
    va_end(ap);
  }
  return rc;
}







/* Prepare a statement using text placed inside a Blob
** using blob_append_sql().
*/
int db_prepare_blob(Stmt *pStmt, Blob *pSql){
  int rc;
  char *zSql;
  pStmt->sql = *pSql;

Deleted src/deltafunc.c.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
/*
** Copyright (c) 2019 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This module implements SQL interfaces to the delta logic.  The code
** here is adapted from the ext/misc/fossildelta.c extension in SQLite.
*/
#include "config.h"
#include "deltafunc.h"

/*
** SQL functions:  delta_create(X,Y)
**
** Return a delta that will transform X into Y.
*/
static void deltaCreateFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aOrig; int nOrig;  /* old blob */
  const char *aNew;  int nNew;   /* new blob */
  char *aOut;        int nOut;   /* output delta */

  assert( argc==2 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nNew = sqlite3_value_bytes(argv[1]);
  aNew = (const char*)sqlite3_value_blob(argv[1]);
  aOut = sqlite3_malloc64(nNew+70);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut = delta_create(aOrig, nOrig, aNew, nNew, aOut);
    if( nOut<0 ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "cannot create fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}

/*
** SQL functions:  delta_apply(X,D)
**
** Return the result of applying delta D to input X.
*/
static void deltaApplyFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aOrig;   int nOrig;        /* The X input */
  const char *aDelta;  int nDelta;       /* The input delta (D) */
  char *aOut;          int nOut, nOut2;  /* The output */

  assert( argc==2 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
  nOrig = sqlite3_value_bytes(argv[0]);
  aOrig = (const char*)sqlite3_value_blob(argv[0]);
  nDelta = sqlite3_value_bytes(argv[1]);
  aDelta = (const char*)sqlite3_value_blob(argv[1]);

  /* Figure out the size of the output */
  nOut = delta_output_size(aDelta, nDelta);
  if( nOut<0 ){
    sqlite3_result_error(context, "corrupt fossil delta", -1);
    return;
  }
  aOut = sqlite3_malloc64((sqlite3_int64)nOut+1);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut2 = delta_apply(aOrig, nOrig, aDelta, nDelta, aOut);
    if( nOut2!=nOut ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "corrupt fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}


/*
** SQL functions:  delta_output_size(D)
**
** Return the size of the output that results from applying delta D.
*/
static void deltaOutputSizeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *aDelta;  int nDelta;       /* The input delta (D) */
  int nOut;                              /* Size of output */
  assert( argc==1 );
  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
  nDelta = sqlite3_value_bytes(argv[0]);
  aDelta = (const char*)sqlite3_value_blob(argv[0]);

  /* Figure out the size of the output */
  nOut = delta_output_size(aDelta, nDelta);
  if( nOut<0 ){
    sqlite3_result_error(context, "corrupt fossil delta", -1);
    return;
  }else{
    sqlite3_result_int(context, nOut);
  }
}

/*****************************************************************************
** Table-valued SQL function:   delta_parse(DELTA)
**
** Schema:
**
**     CREATE TABLE delta_parse(
**       op TEXT,
**       a1 INT,
**       a2 ANY,
**       delta HIDDEN BLOB
**     );
**
** Given an input DELTA, this function parses the delta and returns
** rows for each entry in the delta.  The op column has one of the
** values SIZE, COPY, INSERT, CHECKSUM, ERROR.
**
** Assuming no errors, the first row has op='SIZE'.  a1 is the size of
** the output in bytes and a2 is NULL.
**
** After the initial SIZE row, there are zero or more 'COPY' and/or 'INSERT'
** rows.  A COPY row means content is copied from the source into the
** output.  Column a1 is the number of bytes to copy and a2 is the offset
** into source from which to begin copying.  An INSERT row means to
** insert text into the output stream.  Column a1 is the number of bytes
** to insert and column is a BLOB that contains the text to be inserted.
**
** The last row of a well-formed delta will have an op value of 'CHECKSUM'.
** The a1 column will be the value of the checksum and a2 will be NULL.
**
** If the input delta is not well-formed, then a row with an op value
** of 'ERROR' is returned.  The a1 value of the ERROR row is the offset
** into the delta where the error was encountered and a2 is NULL.
*/
typedef struct deltaparsevtab_vtab deltaparsevtab_vtab;
typedef struct deltaparsevtab_cursor deltaparsevtab_cursor;
struct deltaparsevtab_vtab {
  sqlite3_vtab base;  /* Base class - must be first */
  /* No additional information needed */
};
struct deltaparsevtab_cursor {
  sqlite3_vtab_cursor base;  /* Base class - must be first */
  char *aDelta;              /* The delta being parsed */
  int nDelta;                /* Number of bytes in the delta */
  int iCursor;               /* Current cursor location */
  int eOp;                   /* Name of current operator */
  unsigned int a1, a2;       /* Arguments to current operator */
  int iNext;                 /* Next cursor value */
};

/* Operator names:
*/
static const char *azOp[] = {
  "SIZE", "COPY", "INSERT", "CHECKSUM", "ERROR", "EOF"
};
#define DELTAPARSE_OP_SIZE         0
#define DELTAPARSE_OP_COPY         1
#define DELTAPARSE_OP_INSERT       2
#define DELTAPARSE_OP_CHECKSUM     3
#define DELTAPARSE_OP_ERROR        4
#define DELTAPARSE_OP_EOF          5

/*
** Read bytes from *pz and convert them into a positive integer.  When
** finished, leave *pz pointing to the first character past the end of
** the integer.  The *pLen parameter holds the length of the string
** in *pz and is decremented once for each character in the integer.
*/
static unsigned int deltaGetInt(const char **pz, int *pLen){
  static const signed char zValue[] = {
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
     0,  1,  2,  3,  4,  5,  6,  7,    8,  9, -1, -1, -1, -1, -1, -1,
    -1, 10, 11, 12, 13, 14, 15, 16,   17, 18, 19, 20, 21, 22, 23, 24,
    25, 26, 27, 28, 29, 30, 31, 32,   33, 34, 35, -1, -1, -1, -1, 36,
    -1, 37, 38, 39, 40, 41, 42, 43,   44, 45, 46, 47, 48, 49, 50, 51,
    52, 53, 54, 55, 56, 57, 58, 59,   60, 61, 62, -1, -1, -1, 63, -1,
  };
  unsigned int v = 0;
  int c;
  unsigned char *z = (unsigned char*)*pz;
  unsigned char *zStart = z;
  while( (c = zValue[0x7f&*(z++)])>=0 ){
     v = (v<<6) + c;
  }
  z--;
  *pLen -= z - zStart;
  *pz = (char*)z;
  return v;
}

/*
** The deltaparsevtabConnect() method is invoked to create a new
** deltaparse virtual table.
**
** Think of this routine as the constructor for deltaparsevtab_vtab objects.
**
** All this routine needs to do is:
**
**    (1) Allocate the deltaparsevtab_vtab object and initialize all fields.
**
**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
**        result set of queries against the virtual table will look like.
*/
static int deltaparsevtabConnect(
  sqlite3 *db,
  void *pAux,
  int argc, const char *const*argv,
  sqlite3_vtab **ppVtab,
  char **pzErr
){
  deltaparsevtab_vtab *pNew;
  int rc;

  rc = sqlite3_declare_vtab(db,
           "CREATE TABLE x(op,a1,a2,delta HIDDEN)"
       );
  /* For convenience, define symbolic names for the index to each column. */
#define DELTAPARSEVTAB_OP     0
#define DELTAPARSEVTAB_A1     1
#define DELTAPARSEVTAB_A2     2
#define DELTAPARSEVTAB_DELTA  3
  if( rc==SQLITE_OK ){
    pNew = sqlite3_malloc64( sizeof(*pNew) );
    *ppVtab = (sqlite3_vtab*)pNew;
    if( pNew==0 ) return SQLITE_NOMEM;
    memset(pNew, 0, sizeof(*pNew));
  }
  return rc;
}

/*
** This method is the destructor for deltaparsevtab_vtab objects.
*/
static int deltaparsevtabDisconnect(sqlite3_vtab *pVtab){
  deltaparsevtab_vtab *p = (deltaparsevtab_vtab*)pVtab;
  sqlite3_free(p);
  return SQLITE_OK;
}

/*
** Constructor for a new deltaparsevtab_cursor object.
*/
static int deltaparsevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  deltaparsevtab_cursor *pCur;
  pCur = sqlite3_malloc( sizeof(*pCur) );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, sizeof(*pCur));
  *ppCursor = &pCur->base;
  return SQLITE_OK;
}

/*
** Destructor for a deltaparsevtab_cursor.
*/
static int deltaparsevtabClose(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  sqlite3_free(pCur);
  return SQLITE_OK;
}


/*
** Advance a deltaparsevtab_cursor to its next row of output.
*/
static int deltaparsevtabNext(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  const char *z;
  int i = 0;

  pCur->iCursor = pCur->iNext;
  z = pCur->aDelta + pCur->iCursor;
  pCur->a1 = deltaGetInt(&z, &i);
  switch( z[0] ){
    case '@': {
      z++;
      pCur->a2 = deltaGetInt(&z, &i);
      pCur->eOp = DELTAPARSE_OP_COPY;
      pCur->iNext = (int)(&z[1] - pCur->aDelta);
      break;
    }
    case ':': {
      z++;
      pCur->a2 = (unsigned int)(z - pCur->aDelta);
      pCur->eOp = DELTAPARSE_OP_INSERT;
      pCur->iNext = (int)(&z[pCur->a1] - pCur->aDelta);
      break;
    }
    case ';': {
      pCur->eOp = DELTAPARSE_OP_CHECKSUM;
      pCur->iNext = pCur->nDelta;
      break;
    }
    default: {
      if( pCur->iNext==pCur->nDelta ){
        pCur->eOp = DELTAPARSE_OP_EOF;
      }else{
        pCur->eOp = DELTAPARSE_OP_ERROR;
        pCur->iNext = pCur->nDelta;
      }
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return values of columns for the row at which the deltaparsevtab_cursor
** is currently pointing.
*/
static int deltaparsevtabColumn(
  sqlite3_vtab_cursor *cur,   /* The cursor */
  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  int i                       /* Which column to return */
){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  switch( i ){
    case DELTAPARSEVTAB_OP: {
      sqlite3_result_text(ctx, azOp[pCur->eOp], -1, SQLITE_STATIC);
      break;
    }
    case DELTAPARSEVTAB_A1: {
      sqlite3_result_int(ctx, pCur->a1);
      break;
    }
    case DELTAPARSEVTAB_A2: {
      if( pCur->eOp==DELTAPARSE_OP_COPY ){
        sqlite3_result_int(ctx, pCur->a2);
      }else if( pCur->eOp==DELTAPARSE_OP_INSERT ){
        sqlite3_result_blob(ctx, pCur->aDelta+pCur->a2, pCur->a1,
                            SQLITE_TRANSIENT);
      }
      break;
    }
    case DELTAPARSEVTAB_DELTA: {
      sqlite3_result_blob(ctx, pCur->aDelta, pCur->nDelta, SQLITE_TRANSIENT);
      break;
    }
  }
  return SQLITE_OK;
}

/*
** Return the rowid for the current row.  In this implementation, the
** rowid is the same as the output value.
*/
static int deltaparsevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  *pRowid = pCur->iCursor;
  return SQLITE_OK;
}

/*
** Return TRUE if the cursor has been moved off of the last
** row of output.
*/
static int deltaparsevtabEof(sqlite3_vtab_cursor *cur){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor*)cur;
  return pCur->eOp==DELTAPARSE_OP_EOF;
}

/*
** This method is called to "rewind" the deltaparsevtab_cursor object back
** to the first row of output.  This method is always called at least
** once prior to any call to deltaparsevtabColumn() or deltaparsevtabRowid() or 
** deltaparsevtabEof().
*/
static int deltaparsevtabFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idxNum, const char *idxStr,
  int argc, sqlite3_value **argv
){
  deltaparsevtab_cursor *pCur = (deltaparsevtab_cursor *)pVtabCursor;
  const char *a;
  int i = 0;
  pCur->eOp = DELTAPARSE_OP_ERROR;
  if( idxNum!=1 ){
    return SQLITE_OK;
  }
  pCur->nDelta = sqlite3_value_bytes(argv[0]);
  a = (const char*)sqlite3_value_blob(argv[0]);
  if( pCur->nDelta==0 || a==0 ){
    return SQLITE_OK;
  }
  pCur->aDelta = sqlite3_malloc64( pCur->nDelta+1 );
  if( pCur->aDelta==0 ){
    pCur->nDelta = 0;
    return SQLITE_NOMEM;
  }
  memcpy(pCur->aDelta, a, pCur->nDelta);
  pCur->aDelta[pCur->nDelta] = 0;
  a = pCur->aDelta;
  pCur->eOp = DELTAPARSE_OP_SIZE;
  pCur->a1 = deltaGetInt(&a, &i);
  if( a[0]!='\n' ){
    pCur->eOp = DELTAPARSE_OP_ERROR;
    pCur->a1 = pCur->a2 = 0;
    pCur->iNext = pCur->nDelta;
    return SQLITE_OK;
  }
  a++;
  pCur->iNext = (unsigned int)(a - pCur->aDelta);
  return SQLITE_OK;
}

/*
** SQLite will invoke this method one or more times while planning a query
** that uses the virtual table.  This routine needs to create
** a query plan for each invocation and compute an estimated cost for that
** plan.
*/
static int deltaparsevtabBestIndex(
  sqlite3_vtab *tab,
  sqlite3_index_info *pIdxInfo
){
  int i;
  for(i=0; i<pIdxInfo->nConstraint; i++){
    if( pIdxInfo->aConstraint[i].iColumn != DELTAPARSEVTAB_DELTA ) continue;
    if( pIdxInfo->aConstraint[i].usable==0 ) continue;
    if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
    pIdxInfo->aConstraintUsage[i].omit = 1;
    pIdxInfo->estimatedCost = (double)1;
    pIdxInfo->estimatedRows = 10;
    pIdxInfo->idxNum = 1;
    return SQLITE_OK;
  }
  pIdxInfo->idxNum = 0;
  pIdxInfo->estimatedCost = (double)0x7fffffff;
  pIdxInfo->estimatedRows = 0x7fffffff;
  return SQLITE_CONSTRAINT;
}

/*
** This following structure defines all the methods for the 
** virtual table.
*/
static sqlite3_module deltaparsevtabModule = {
  /* iVersion    */ 0,
  /* xCreate     */ 0,
  /* xConnect    */ deltaparsevtabConnect,
  /* xBestIndex  */ deltaparsevtabBestIndex,
  /* xDisconnect */ deltaparsevtabDisconnect,
  /* xDestroy    */ 0,
  /* xOpen       */ deltaparsevtabOpen,
  /* xClose      */ deltaparsevtabClose,
  /* xFilter     */ deltaparsevtabFilter,
  /* xNext       */ deltaparsevtabNext,
  /* xEof        */ deltaparsevtabEof,
  /* xColumn     */ deltaparsevtabColumn,
  /* xRowid      */ deltaparsevtabRowid,
  /* xUpdate     */ 0,
  /* xBegin      */ 0,
  /* xSync       */ 0,
  /* xCommit     */ 0,
  /* xRollback   */ 0,
  /* xFindMethod */ 0,
  /* xRename     */ 0,
  /* xSavepoint  */ 0,
  /* xRelease    */ 0,
  /* xRollbackTo */ 0,
  /* xShadowName */ 0
};

/*
** Invoke this routine to register the various delta functions.
*/
int deltafunc_init(sqlite3 *db){
  int rc = SQLITE_OK;
  rc = sqlite3_create_function(db, "delta_create", 2, SQLITE_UTF8, 0,
                               deltaCreateFunc, 0, 0);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "delta_apply", 2, SQLITE_UTF8, 0,
                                 deltaApplyFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "delta_output_size", 1, SQLITE_UTF8, 0,
                                 deltaOutputSizeFunc, 0, 0);
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_module(db, "delta_parse", &deltaparsevtabModule, 0);
  }
  return rc;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Changes to src/export.c.

26
27
28
29
30
31
32
33
34






35
36
37
38


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
...
296
297
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313
314
315
316
317
...
360
361
362
363
364
365
366

367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
...
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
*/
static struct {
  const char *zTrunkName;     /* Name of trunk branch */
} gexport;

#if INTERFACE
/*
** Each line in a git-fast-export "marK" file is an instance of
** this object.






*/
struct mark_t {
  char *name;       /* Name of the mark.  Also starts with ":" */
  int rid;          /* Corresponding object in the BLOB table */


  char uuid[65];    /* The GIT hash name for this object */
};
#endif

#if defined(_WIN32) || defined(WIN32)
# undef popen
# define popen _popen
# undef pclose
# define pclose _pclose
#endif

/*
** Output a "committer" record for the given user.
** NOTE: the given user name may be an email itself.
*/
static void print_person(const char *zUser){
  static Stmt q;
  const char *zContact;
................................................................................
      return NULL;
    }
  }
  return zMark;
}

/*
** Parse a single line of the mark file.  Store the result in the mark object.
**
** "line" is a single line of input.

** This function returns -1 in the case that the line is blank, malformed, or
** the rid/uuid named in 'line' does not match what is in the repository
** database.  Otherwise, 0 is returned.
**
** mark->name is dynamically allocated, and owned by the caller.
*/
int parse_mark(char *line, struct mark_t *mark){
  char *cur_tok;
  char type_;
  cur_tok = strtok(line, " \t");
  if( !cur_tok || strlen(cur_tok)<2 ){
    return -1;
................................................................................

  /* insert a cross-ref into the 'xmark' table */
  insert_commit_xref(mark->rid, mark->name, mark->uuid);
  return 0;
}

/*

** Import the marks specified in file 'f';
** If 'blobs' is non-null, insert all blob marks into it.
** If 'vers' is non-null, insert all commit marks into it.
** If 'unused_marks' is non-null, upon return of this function, all values
** x >= *unused_marks are free to use as marks, i.e. they do not clash with
** any marks appearing in the marks file.
**
** Each line in the file must be at most 100 characters in length.  This
** seems like a reasonable maximum for a 40-character uuid, and 1-13
** character rid.
**
** The function returns -1 if any of the lines in file 'f' are malformed,
** or the rid/uuid information doesn't match what is in the repository
** database.  Otherwise, 0 is returned.
*/
int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
  char line[101];
  while(fgets(line, sizeof(line), f)){
    struct mark_t mark;
    if( strlen(line)==100 && line[99]!='\n' ){
      /* line too long */
................................................................................
      do{
        export_mark(f, rid, 'c');
      }while( (rid = bag_next(vers, rid))!=0 );
    }
  }
}

/* This is the original header command (and hence documentation) for
** the "fossil export" command:
** 
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
**
** Write an export of all check-ins to standard output.  The export is
** written in the git-fast-export file format assuming the --git option is
** provided.  The git-fast-export format is currently the only VCS
** interchange format supported, though other formats may be added in
** the future.
................................................................................
**   --export-marks FILE          export rids of exported data to FILE
**   --import-marks FILE          read rids of data to ignore from FILE
**   --rename-trunk NAME          use NAME as name of exported trunk branch
**   --repository|-R REPOSITORY   export the given REPOSITORY
**
** See also: import
*/
/*
** COMMAND: export*
**
** This command is deprecated.  Use "fossil git export" instead.
*/
void export_cmd(void){
  Stmt q, q2, q3;
  Bag blobs, vers;
  unsigned int unused_mark = 1;
  const char *markfile_in;
  const char *markfile_out;

................................................................................

  db_find_and_open_repository(0, 2);
  verify_all_options();
  if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }

  db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
  db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
  db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT,"
                " tuuid TEXT)");
  db_multi_exec("CREATE INDEX xmark_trid ON xmark(trid)");
  if( markfile_in!=0 ){
    Stmt qb,qc;
    FILE *f;
    int rid;

    f = fossil_fopen(markfile_in, "r");
................................................................................
**        tid INTEGER PRIMARY KEY,   -- Check-in id
**        tseq INT                   -- integer total order on check-ins.
**     );
**
** This table contains all check-ins of the repository in topological
** order.  "Topological order" means that every parent check-in comes
** before all of its children.  Topological order is *almost* the same
** thing as "ORDER BY event.mtime".  Differences only arise when there
** are timewarps.  In as much as Git hates timewarps, we have to compute
** a correct topological order when doing an export.
**
** Since mtime is a usually already nearly in topological order, the
** algorithm is to start with mtime, then make adjustments as necessary
** for timewarps.  This is not a great algorithm for the general case,
** but it is very fast for the overwhelmingly common case where there
................................................................................
*/
void test_topological_sort(void){
  int n;
  db_find_and_open_repository(0, 0);
  n = topological_sort_checkins(1);
  fossil_print("%d reorderings required\n", n);
}

/***************************************************************************
** Implementation of the "fossil git" command follows.  We hope that the
** new code that follows will largely replace the legacy "fossil export"
** and "fossil import" code above.
*/

/* Verbosity level.  Higher means more output.
**
**    0     print nothing at all
**    1     Errors only
**    2     Progress information (This is the default)
**    3     Extra details
*/
#define VERB_ERROR  1
#define VERB_NORMAL 2
#define VERB_EXTRA  3
static int gitmirror_verbosity = VERB_NORMAL;

/*
** Output routine that depends on verbosity
*/
static void gitmirror_message(int iLevel, const char *zFormat, ...){
  va_list ap;
  if( iLevel>gitmirror_verbosity ) return;
  va_start(ap, zFormat);
  fossil_vprint(zFormat, ap);
  va_end(ap);
}

/*
** Convert characters of z[] that are not allowed to be in branch or
** tag names into "_".
*/
static void gitmirror_sanitize_name(char *z){
  static unsigned char aSafe[] = {
     /* x0 x1 x2 x3 x4 x5 x6 x7 x8  x9 xA xB xC xD xE xF */
         0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  /* 0x */
         0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0,  /* 1x */
         0, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1,  /* 2x */
         1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 0, 1, 1, 1, 1, 0,  /* 3x */
         0, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1,  /* 4x */
         1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 0, 0, 1, 0, 1,  /* 5x */
         1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1,  /* 6x */
         1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 0, 0,  /* 7x */
  };
  unsigned char *zu = (unsigned char*)z;
  int i;
  for(i=0; zu[i]; i++){
    if( zu[i]>0x7f || !aSafe[zu[i]] ){
      zu[i] = '_';
    }else if( zu[i]=='/' && (i==0 || zu[i+1]==0 || zu[i+1]=='/') ){
      zu[i] = '_';
    }else if( zu[i]=='.' && (zu[i+1]==0 || zu[i+1]=='.'
                             || (i>0 && zu[i-1]=='.')) ){
      zu[i] = '_';
    }
  }
}

/*
** Quote a filename as a C-style string using \\ and \" if necessary.
** If quoting is not necessary, just return a copy of the input string.
**
** The return value is a held in memory obtained from fossil_malloc()
** and must be freed by the caller.
*/
static char *gitmirror_quote_filename_if_needed(const char *zIn){
  int i, j;
  char c;
  int nSpecial = 0;
  char *zOut;
  for(i=0; (c = zIn[i])!=0; i++){
    if( c=='\\' || c=='"' || c=='\n' ){
      nSpecial++;
    }
  }
  if( nSpecial==0 ){
    return fossil_strdup(zIn);
  }
  zOut = fossil_malloc( i+nSpecial+3 );
  zOut[0] = '"';
  for(i=0, j=1; (c = zIn[i])!=0; i++){
    if( c=='\\' || c=='"' || c=='\n' ){
      zOut[j++] = '\\';
      if( c=='\n' ){
        zOut[j++] = 'n';
      }else{
        zOut[j++] = c;
      }
    }else{
      zOut[j++] = c;
    }
  }
  zOut[j++] = '"';
  zOut[j] = 0;
  return zOut;
}

/*
** Find the Git-name corresponding to the Fossil-name zUuid.
**
** If the mark does not exist and if the bCreate flag is false, then
** return NULL.  If the mark does not exist and the bCreate flag is true,
** then create the mark.
**
** The string returned is obtained from fossil_malloc() and should
** be freed by the caller.
*/
static char *gitmirror_find_mark(const char *zUuid, int bCreate){
  static Stmt sFind, sIns;
  db_static_prepare(&sFind,
    "SELECT coalesce(githash,printf(':%%d',id))"
    " FROM mirror.mmark WHERE uuid=:uuid"
  );
  db_bind_text(&sFind, ":uuid", zUuid);
  if( db_step(&sFind)==SQLITE_ROW ){
    char *zMark = fossil_strdup(db_column_text(&sFind, 0));
    db_reset(&sFind);
    return zMark;
  }
  db_reset(&sFind);
  if( !bCreate ){
    return 0;
  }
  db_static_prepare(&sIns,
    "INSERT INTO mirror.mmark(uuid) VALUES(:uuid)"
  );
  db_bind_text(&sIns, ":uuid", zUuid);
  db_step(&sIns);
  db_reset(&sIns);
  return mprintf(":%d", db_last_insert_rowid());
}

/* This is the SHA3-256 hash of an empty file */
static const char zEmptySha3[] = 
  "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";

/*
** Export a single file named by zUuid.
**
** Return 0 on success and non-zero on any failure.
**
** If zUuid is a shunned file, then treat it as if it were any empty file.
** But files that are missing from the repository but have not been officially
** shunned cause an error return.  Except, if bPhantomOk is true, then missing
** files are replaced by an empty file.
*/
static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
  char *zMark;
  int rid;
  int rc;
  Blob data;
  rid = fast_uuid_to_rid(zUuid);
  if( rid<0 ){
    if( bPhantomOk || uuid_is_shunned(zUuid) ){
      gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
      zUuid = zEmptySha3;
    }else{
      return 1;
    }
  }else{
    rc = content_get(rid, &data);
    if( rc==0 ){
      if( bPhantomOk ){
        blob_init(&data, 0, 0);
        gitmirror_message(VERB_EXTRA, "missing file: %s\n", zUuid);
        zUuid = zEmptySha3;
      }else{      
        return 1;
      }
    }
  }
  zMark = gitmirror_find_mark(zUuid, 1);
  if( zMark[0]==':' ){
    fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
    fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
    fprintf(xCmd, "\n");
  }
  fossil_free(zMark);
  blob_reset(&data);
  return 0;
}

/*
** Transfer a check-in over to the mirror.  "rid" is the BLOB.RID for
** the check-in to export.
**
** If any ancestor of the check-in has not yet been exported, then
** invoke this routine recursively to export the ancestor first.
** This can only happen on a timewarp, so deep nesting is unlikely.
**
** Before sending the check-in, first make sure all associated files
** have already been exported, and send "blob" records for any that
** have not been.  Update the MIRROR.MMARK table so that it holds the
** marks for the exported files.
**
** Return zero on success and non-zero if the export should be stopped.
*/
static int gitmirror_send_checkin(
  FILE *xCmd,           /* Write fast-import text on this pipe */
  int rid,              /* BLOB.RID for the check-in to export */
  const char *zUuid,    /* BLOB.UUID for the check-in to export */
  int *pnLimit,         /* Stop when the counter reaches zero */
  int fManifest         /* MFESTFLG_* values */
){
  Manifest *pMan;       /* The check-in to be output */
  int i;                /* Loop counter */
  int iParent;          /* Which immediate ancestor is primary.  -1 for none */
  Stmt q;               /* An SQL query */
  char *zBranch;        /* The branch of the check-in */
  char *zMark;          /* The Git-name of the check-in */
  Blob sql;             /* String of SQL for part of the query */
  Blob comment;         /* The comment text for the check-in */
  int nErr = 0;         /* Number of errors */
  int bPhantomOk;       /* True if phantom files should be ignored */

  pMan = manifest_get(rid, CFTYPE_MANIFEST, 0);
  if( pMan==0 ){
    /* Must be a phantom.  Return without doing anything, and in particular
    ** without creating a mark for this check-in. */
    gitmirror_message(VERB_NORMAL, "missing check-in: %s\n", zUuid);
    return 0;
  }

  /* Check to see if any parent logins have not yet been processed, and
  ** if so, create them */
  for(i=0; i<pMan->nParent; i++){
    char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0);
    if( zPMark==0 ){
      int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
                        pMan->azParent[i]);
      int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
                                      pnLimit, fManifest);
      if( rc || *pnLimit<=0 ){
        manifest_destroy(pMan);
        return 1;
      }
    }
    fossil_free(zPMark);
  }

  /* Ignore phantom files on check-ins that are over one year old */
  bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
                      pMan->rDate);

  /* Make sure all necessary files have been exported */
  db_prepare(&q,
    "SELECT uuid FROM files_of_checkin(%Q)"
    " WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
    zUuid
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFUuid = db_column_text(&q, 0);
    int n = gitmirror_send_file(xCmd, zFUuid, bPhantomOk);
    nErr += n;
    if( n ) gitmirror_message(VERB_ERROR, "missing file: %s\n", zFUuid);
  }
  db_finalize(&q);

  /* If some required files could not be exported, abandon the check-in
  ** export */
  if( nErr ){
    gitmirror_message(VERB_ERROR,
             "export of %s abandoned due to missing files\n", zUuid);
    *pnLimit = 0;
    return 1;
  }

  /* Figure out which branch this check-in is a member of */
  zBranch = db_text(0,
    "SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0 AND rid=%d",
    TAG_BRANCH, rid
  );
  if( fossil_strcmp(zBranch,"trunk")==0 ){
    fossil_free(zBranch);
    zBranch = mprintf("master");
  }else if( zBranch==0 ){
    zBranch = mprintf("unknown");
  }else{
    gitmirror_sanitize_name(zBranch);
  }

  /* Export the check-in */
  fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
  fossil_free(zBranch);
  zMark = gitmirror_find_mark(zUuid,1);
  fprintf(xCmd, "mark %s\n", zMark);
  fossil_free(zMark);
  fprintf(xCmd, "committer %s <%s@noemail.net> %lld +0000\n",
     pMan->zUser, pMan->zUser, 
     (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
  );
  blob_init(&comment, pMan->zComment, -1);
  if( blob_size(&comment)==0 ){
    blob_append(&comment, "(no comment)", -1);
  }
  blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
  fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
  blob_reset(&comment);
  iParent = -1;  /* Which ancestor is the primary parent */
  for(i=0; i<pMan->nParent; i++){
    char *zOther = gitmirror_find_mark(pMan->azParent[i], 0);
    if( zOther==0 ) continue;
    if( iParent<0 ){
      iParent = i;
      fprintf(xCmd, "from %s\n", zOther);
    }else{
      fprintf(xCmd, "merge %s\n", zOther);
    }
    fossil_free(zOther);
  }
  if( iParent>=0 ){
    db_prepare(&q,
      "SELECT filename FROM files_of_checkin(%Q)"
      " EXCEPT SELECT filename FROM files_of_checkin(%Q)",
      pMan->azParent[iParent], zUuid
    );
    while( db_step(&q)==SQLITE_ROW ){
      fprintf(xCmd, "D %s\n", db_column_text(&q,0));
    }
    db_finalize(&q);
  }
  blob_init(&sql, 0, 0);
  blob_append_sql(&sql,
    "SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
    zUuid
  );
  if( pMan->nParent ){
    blob_append_sql(&sql,
      " EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
      pMan->azParent[0]);
  }
  db_prepare(&q,
     "SELECT x.filename, x.perm,"
          "  coalesce(mmark.githash,printf(':%%d',mmark.id))"
     "  FROM (%s) AS x, mirror.mmark"
     " WHERE mmark.uuid=x.uuid",
     blob_sql_text(&sql)
  );
  blob_reset(&sql);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFilename = db_column_text(&q,0);
    const char *zMode = db_column_text(&q,1);
    const char *zMark = db_column_text(&q,2);
    const char *zGitMode = "100644";
    char *zFNQuoted = 0;
    if( zMode ){
      if( strchr(zMode,'x') ) zGitMode = "100755";
      if( strchr(zMode,'l') ) zGitMode = "120000";
    }
    zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
    fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted);
    fossil_free(zFNQuoted);
  }
  db_finalize(&q);

  /* Include Fossil-generated auxiliary files in the check-in */
  if( fManifest & MFESTFLG_RAW ){
    Blob manifest;
    content_get(rid, &manifest);
    fprintf(xCmd,"M 100644 inline manifest\ndata %d\n%s\n",
      blob_size(&manifest), blob_str(&manifest));
    blob_reset(&manifest);
  }
  if( fManifest & MFESTFLG_UUID ){
    int n = (int)strlen(zUuid);
    fprintf(xCmd,"M 100644 inline manifest.uuid\ndata %d\n%s\n", n, zUuid);
  }
  if( fManifest & MFESTFLG_TAGS ){
    Blob tagslist;
    blob_init(&tagslist, 0, 0);
    get_checkin_taglist(rid, &tagslist);
    fprintf(xCmd,"M 100644 inline manifest.tags\ndata %d\n%s\n",
      blob_size(&tagslist), blob_str(&tagslist));
    blob_reset(&tagslist);
  }

  /* The check-in is finished, so decrement the counter */
  (*pnLimit)--;
  return 0;
}

/*
** Implementation of the "fossil git export" command.
*/
void gitmirror_export_command(void){
  const char *zLimit;             /* Text of the --limit flag */
  int nLimit = 0x7fffffff;        /* Numeric value of the --limit flag */
  int nTotal = 0;                 /* Total number of check-ins to export */
  char *zMirror;                  /* Name of the mirror */
  char *z;                        /* Generic string */
  char *zCmd;                     /* git command to run as a subprocess */
  const char *zDebug = 0;         /* Value of the --debug flag */
  const char *zAutoPush = 0;      /* Value of the --autopush flag */
  char *zPushUrl;                 /* URL to sync the mirror to */
  double rEnd;                    /* time of most recent export */
  int rc;                         /* Result code */
  int bForce;                     /* Do the export and sync even if no changes*/
  int bNeedRepack = 0;            /* True if we should run repack at the end */
  int fManifest;                  /* Current "manifest" setting */
  FILE *xCmd;                     /* Pipe to the "git fast-import" command */
  FILE *pMarks;                   /* Git mark files */
  Stmt q;                         /* Queries */
  char zLine[200];                /* One line of a mark file */

  zDebug = find_option("debug",0,1);
  db_find_and_open_repository(0, 0);
  zLimit = find_option("limit", 0, 1);
  if( zLimit ){
    nLimit = (unsigned int)atoi(zLimit);
    if( nLimit<=0 ) fossil_fatal("--limit must be positive");
  }
  zAutoPush = find_option("autopush",0,1);
  bForce = find_option("force","f",0)!=0;
  gitmirror_verbosity = VERB_NORMAL;
  while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; }
  while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; }
  verify_all_options();
  if( g.argc!=4 && g.argc!=3 ){ usage("export ?MIRROR?"); }
  if( g.argc==4 ){
    Blob mirror;
    file_canonical_name(g.argv[3], &mirror, 0);
    db_set("last-git-export-repo", blob_str(&mirror), 0);
    blob_reset(&mirror);
  }
  zMirror = db_get("last-git-export-repo", 0);
  if( zMirror==0 ){
    fossil_fatal("no Git repository specified");
  }

  /* Make sure the GIT repository directory exists */
  rc = file_mkdir(zMirror, ExtFILE, 0);
  if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);

  /* Make sure GIT has been initialized */
  z = mprintf("%s/.git", zMirror);
  if( !file_isdir(z, ExtFILE) ){
    zCmd = mprintf("git init '%s'",zMirror);
    gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
    rc = fossil_system(zCmd);
    if( rc ){
      fossil_fatal("cannot initialize the git repository using: \"%s\"", zCmd);
    }
    fossil_free(zCmd);
    bNeedRepack = 1;
  }
  fossil_free(z);
  
  /* Make sure the .mirror_state subdirectory exists */
  z = mprintf("%s/.mirror_state", zMirror);
  rc = file_mkdir(z, ExtFILE, 0);
  if( rc ) fossil_fatal("cannot create directory \"%s\"", z);
  fossil_free(z);

  /* Attach the .mirror_state/db database */
  db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror);
  db_begin_write();
  db_multi_exec(
    "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n"
    "  key TEXT PRIMARY KEY,\n"
    "  Value ANY\n"
    ") WITHOUT ROWID;\n"
    "CREATE TABLE IF NOT EXISTS mirror.mmark(\n"
    "  id INTEGER PRIMARY KEY,\n"
    "  uuid TEXT UNIQUE,\n"
    "  githash TEXT\n"
    ");"
  );

  /* Change the autopush setting if the --autopush flag is present */
  if( zAutoPush ){
    if( is_false(zAutoPush) ){
      db_multi_exec("DELETE FROM mirror.mconfig WHERE key='autopush'");
    }else{
      db_multi_exec(
         "REPLACE INTO mirror.mconfig(key,value)"
         "VALUES('autopush',%Q)",
         zAutoPush
      );
    }
  }

  /* See if there is any work to be done.  Exit early if not, before starting
  ** the "git fast-import" command. */
  if( !bForce
   && !db_exists("SELECT 1 FROM event WHERE type IN ('ci','t')"
                 " AND mtime>coalesce((SELECT value FROM mconfig"
                                        " WHERE key='start'),0.0)")
  ){
    gitmirror_message(VERB_NORMAL, "no changes\n");
    db_commit_transaction();
    return;
  }

  /* Do we need to include manifest files in the clone? */
  fManifest = db_get_manifest_setting();

  /* Change to the MIRROR directory so that the Git commands will work */
  rc = file_chdir(zMirror, 0);
  if( rc ) fossil_fatal("cannot change the working directory to \"%s\"",
                        zMirror);

  /* Start up the git fast-import command */
  if( zDebug ){
    if( fossil_strcmp(zDebug,"stdout")==0 ){
      xCmd = stdout;
    }else{
      xCmd = fopen(zDebug, "wb");
      if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
    }
  }else{
    zCmd = mprintf("git fast-import"
              " --export-marks=.mirror_state/marks.txt"
              " --quiet --done");
    gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
    xCmd = popen(zCmd, "w");
    if( zCmd==0 ){
      fossil_fatal("cannot start the \"git fast-import\" command");
    }
    fossil_free(zCmd);
  }

  /* Run the export */
  rEnd = 0.0;
  db_multi_exec(
    "CREATE TEMP TABLE tomirror(objid,mtime,uuid);\n"
    "INSERT INTO tomirror "
    "SELECT objid, mtime, blob.uuid FROM event, blob\n"
    " WHERE type='ci'"
    "   AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)"
    "   AND blob.rid=event.objid"
    "   AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark);"
  );
  nTotal = db_int(0, "SELECT count(*) FROM tomirror");
  if( nLimit<nTotal ){
    nTotal = nLimit;
  }else if( nLimit>nTotal ){
    nLimit = nTotal;
  }
  db_prepare(&q,
    "SELECT objid, mtime, uuid FROM tomirror ORDER BY mtime"
  );
  while( nLimit && db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    double rMTime = db_column_double(&q, 1);
    const char *zUuid = db_column_text(&q, 2);
    if( rMTime>rEnd ) rEnd = rMTime;
    rc = gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
    if( rc ) break;
    gitmirror_message(VERB_NORMAL,"%d/%d      \r", nTotal-nLimit, nTotal);
    fflush(stdout);
  }
  db_finalize(&q);
  fprintf(xCmd, "done\n");
  if( zDebug ){
    if( xCmd!=stdout ) fclose(xCmd);
  }else{
    pclose(xCmd);
  }
  gitmirror_message(VERB_NORMAL, "%d check-ins added to the %s\n",
                    nTotal-nLimit, zMirror);

  /* Read the export-marks file.  Transfer the new marks over into
  ** the import-marks file.
  */
  pMarks = fopen(".mirror_state/marks.txt", "rb");
  if( pMarks ){
    db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
    while( fgets(zLine, sizeof(zLine), pMarks) ){
      int j, k;
      if( zLine[0]!=':' ) continue;
      db_bind_int(&q, ":id", atoi(zLine+1));
      for(j=1; zLine[j] && zLine[j]!=' '; j++){}
      if( zLine[j]!=' ' ) continue;
      j++;
      if( zLine[j]==0 ) continue;
      for(k=j; fossil_isalnum(zLine[k]); k++){}
      zLine[k] = 0;
      db_bind_text(&q, ":githash", &zLine[j]);
      db_step(&q);
      db_reset(&q);
    }
    db_finalize(&q);
    fclose(pMarks);
    file_delete(".mirror_state/marks.txt");
  }else{
    fossil_fatal("git fast-import didn't generate a marks file!");
  }
  db_multi_exec(
    "CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
  );

  /* Do any tags that have been created since the start time */
  db_prepare(&q,
    "SELECT substr(tagname,5), githash"
    "  FROM (SELECT tagxref.tagid AS xtagid, tagname, rid, max(mtime) AS mtime"
    "          FROM tagxref JOIN tag ON tag.tagid=tagxref.tagid"
    "         WHERE tag.tagname GLOB 'sym-*'"
    "           AND tagxref.tagtype=1"
    "           AND tagxref.mtime > coalesce((SELECT value FROM mconfig"
                                        " WHERE key='start'),0.0)"
    "         GROUP BY tagxref.tagid) AS tx"
    "       JOIN blob ON tx.rid=blob.rid"
    "       JOIN mmark ON mmark.uuid=blob.uuid;"
  );
  while( db_step(&q)==SQLITE_ROW ){
    char *zTagname = fossil_strdup(db_column_text(&q,0));
    const char *zObj = db_column_text(&q,1);
    char *zTagCmd;
    gitmirror_sanitize_name(zTagname);
    zTagCmd = mprintf("git tag -f \"%s\" %s", zTagname, zObj);
    fossil_free(zTagname);
    gitmirror_message(VERB_NORMAL, "%s\n", zTagCmd);
    fossil_system(zTagCmd);
    fossil_free(zTagCmd);
  }
  db_finalize(&q);

  /* Update the start time */
  if( rEnd>0.0 ){
    db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)");
    db_bind_double(&q, ":x", rEnd);
    db_step(&q);
    db_finalize(&q);
  }
  db_commit_transaction();

  /* Maybe run a git repack */
  if( bNeedRepack ){
    const char *zRepack = "git repack -adf";
    gitmirror_message(VERB_NORMAL, "%s\n", zRepack);
    fossil_system(zRepack);
  }

  /* Optionally do a "git push" */
  zPushUrl = db_text(0, "SELECT value FROM mconfig WHERE key='autopush'");
  if( zPushUrl ){
    char *zPushCmd;
    UrlData url;
    if( sqlite3_strglob("http*", zPushUrl)==0 ){
      url_parse_local(zPushUrl, 0, &url);
      zPushCmd = mprintf("git push --mirror %s", url.canonical);
    }else{
      zPushCmd = mprintf("git push --mirror %s", zPushUrl);
    }
    gitmirror_message(VERB_NORMAL, "%s\n", zPushCmd);
    fossil_free(zPushCmd);
    zPushCmd = mprintf("git push --mirror %s", zPushUrl);
    fossil_system(zPushCmd);
    fossil_free(zPushCmd);
  }
}

/*
** COMMAND: git
**
** Usage: %fossil git SUBCOMMAND
**
** Do incremental import or export operations between Fossil and Git.
** Subcommands:
**
**   fossil git export [MIRROR] [OPTIONS]
**
**       Write content from the Fossil repository into the Git repository
**       in directory MIRROR.  The Git repository is created if it does not
**       already exist.  If the Git repository does already exist, then
**       new content added to fossil since the previous export is appended.
**
**       Repeat this command whenever new checkins are added to the Fossil
**       repository in order to reflect those changes into the mirror.  If
**       the MIRROR option is omitted, the repository from the previous
**       invocation is used.
**
**       The MIRROR directory will contain a subdirectory named
**       ".mirror_state" that contains information that Fossil needs to
**       do incremental exports.  Do not attempt to manage or edit the files
**       in that directory since doing so can disrupt future incremental
**       exports.
**
**       Options:
**         --autopush URL      Automatically do a 'git push' to URL.  The
**                             URL is remembered and used on subsequent exports
**                             to the same repository.  Or if URL is "off" the
**                             auto-push mechanism is disabled
**         --debug FILE        Write fast-export text to FILE rather than
**                             piping it into "git fast-import".
**         --force|-f          Do the export even if nothing has changed
**         --limit N           Add no more than N new check-ins to MIRROR.
**                             Useful for debugging
**         --quiet|-q          Reduce output. Repeat for even less output.
**         --verbose|-v        More output.
**
**   fossil git import MIRROR
**
**       TBD...   
*/
void gitmirror_command(void){
  char *zCmd;
  int nCmd;
  if( g.argc<3 ){
    usage("export ARGS...");
  }
  zCmd =  g.argv[2];
  nCmd = (int)strlen(zCmd);
  if( nCmd>2 && strncmp(zCmd,"export",nCmd)==0 ){
    gitmirror_export_command();
  }else
  if( nCmd>2 && strncmp(zCmd,"import",nCmd)==0 ){
    fossil_fatal("not yet implemented - check back later");
  }else
  {
    fossil_fatal("unknown subcommand \"%s\": should be one of "
                 "\"export\", \"import\"",
                 zCmd);
  }
}







|
|
>
>
>
>
>
>

|
<
<
>
>
|



<
<
<
<
<
<
<







 







|
|
|
>
|
|
|
<
|







 







>
|
|
|
|
|
|
<
|
|
|
<
|
|
|







 







|
|
|







 







<
<
<
<
<







 







|
<







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42


43
44
45
46
47
48







49
50
51
52
53
54
55
...
295
296
297
298
299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
...
359
360
361
362
363
364
365
366
367
368
369
370
371
372

373
374
375

376
377
378
379
380
381
382
383
384
385
...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
...
481
482
483
484
485
486
487





488
489
490
491
492
493
494
...
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
...
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
...
833
834
835
836
837
838
839













































































































































































































































































































































































































































































































































































































































































































































*/
static struct {
  const char *zTrunkName;     /* Name of trunk branch */
} gexport;

#if INTERFACE
/*
** struct mark_t
**   holds information for translating between git commits
**   and fossil commits.
**   -git_name: This is the mark name that identifies the commit to git.
**              It will always begin with a ':'.
**   -rid: The unique object ID that identifies this commit within the
**         repository database.
**   -uuid: The SHA-1/SHA-3 of artifact corresponding to rid.
*/
struct mark_t{


  char *name;
  int rid;
  char uuid[65];
};
#endif








/*
** Output a "committer" record for the given user.
** NOTE: the given user name may be an email itself.
*/
static void print_person(const char *zUser){
  static Stmt q;
  const char *zContact;
................................................................................
      return NULL;
    }
  }
  return zMark;
}

/*
** parse_mark()
**   Create a new (mark,rid,uuid) entry in the 'xmark' table given a line
**   from a marks file.  Return the cross-ref information as a struct mark_t
**   in *mark.
**   This function returns -1 in the case that the line is blank, malformed, or
**   the rid/uuid named in 'line' does not match what is in the repository
**   database.  Otherwise, 0 is returned.

**   mark->name is dynamically allocated, and owned by the caller.
*/
int parse_mark(char *line, struct mark_t *mark){
  char *cur_tok;
  char type_;
  cur_tok = strtok(line, " \t");
  if( !cur_tok || strlen(cur_tok)<2 ){
    return -1;
................................................................................

  /* insert a cross-ref into the 'xmark' table */
  insert_commit_xref(mark->rid, mark->name, mark->uuid);
  return 0;
}

/*
** import_marks()
**   Import the marks specified in file 'f' into the 'xmark' table.
**   If 'blobs' is non-null, insert all blob marks into it.
**   If 'vers' is non-null, insert all commit marks into it.
**   If 'unused_marks' is non-null, upon return of this function, all values
**   x >= *unused_marks are free to use as marks, i.e. they do not clash with
**   any marks appearing in the marks file.

**   Each line in the file must be at most 100 characters in length.  This
**   seems like a reasonable maximum for a 40-character uuid, and 1-13
**   character rid.

**   The function returns -1 if any of the lines in file 'f' are malformed,
**   or the rid/uuid information doesn't match what is in the repository
**   database.  Otherwise, 0 is returned.
*/
int import_marks(FILE* f, Bag *blobs, Bag *vers, unsigned int *unused_mark){
  char line[101];
  while(fgets(line, sizeof(line), f)){
    struct mark_t mark;
    if( strlen(line)==100 && line[99]!='\n' ){
      /* line too long */
................................................................................
      do{
        export_mark(f, rid, 'c');
      }while( (rid = bag_next(vers, rid))!=0 );
    }
  }
}

/*
** COMMAND: export
**
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
**
** Write an export of all check-ins to standard output.  The export is
** written in the git-fast-export file format assuming the --git option is
** provided.  The git-fast-export format is currently the only VCS
** interchange format supported, though other formats may be added in
** the future.
................................................................................
**   --export-marks FILE          export rids of exported data to FILE
**   --import-marks FILE          read rids of data to ignore from FILE
**   --rename-trunk NAME          use NAME as name of exported trunk branch
**   --repository|-R REPOSITORY   export the given REPOSITORY
**
** See also: import
*/





void export_cmd(void){
  Stmt q, q2, q3;
  Bag blobs, vers;
  unsigned int unused_mark = 1;
  const char *markfile_in;
  const char *markfile_out;

................................................................................

  db_find_and_open_repository(0, 2);
  verify_all_options();
  if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }

  db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER PRIMARY KEY)");
  db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER PRIMARY KEY)");
  db_multi_exec("CREATE TEMP TABLE xmark(tname TEXT UNIQUE, trid INT, tuuid TEXT)");

  db_multi_exec("CREATE INDEX xmark_trid ON xmark(trid)");
  if( markfile_in!=0 ){
    Stmt qb,qc;
    FILE *f;
    int rid;

    f = fossil_fopen(markfile_in, "r");
................................................................................
**        tid INTEGER PRIMARY KEY,   -- Check-in id
**        tseq INT                   -- integer total order on check-ins.
**     );
**
** This table contains all check-ins of the repository in topological
** order.  "Topological order" means that every parent check-in comes
** before all of its children.  Topological order is *almost* the same
** thing as "ORDER BY event.mtime".  Differences only arrise when there
** are timewarps.  In as much as Git hates timewarps, we have to compute
** a correct topological order when doing an export.
**
** Since mtime is a usually already nearly in topological order, the
** algorithm is to start with mtime, then make adjustments as necessary
** for timewarps.  This is not a great algorithm for the general case,
** but it is very fast for the overwhelmingly common case where there
................................................................................
*/
void test_topological_sort(void){
  int n;
  db_find_and_open_repository(0, 0);
  n = topological_sort_checkins(1);
  fossil_print("%d reorderings required\n", n);
}













































































































































































































































































































































































































































































































































































































































































































































Changes to src/file.c.

435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
...
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
  const char *zTail = file_tail(z);
  if( zTail && zTail!=z ){
    return mprintf("%.*s", (int)(zTail-z-1), z);
  }else{
    return 0;
  }
}

/* SQL Function:  file_dirname(NAME)
**
** Return the directory for NAME
*/
void file_dirname_sql_function(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName = (const char*)sqlite3_value_text(argv[0]);
  char *zDir;
  if( zName==0 ) return;
  zDir = file_dirname(zName);
  if( zDir ){
    sqlite3_result_text(context,zDir,-1,fossil_free);
  }
}


/*
** Rename a file or directory.
** Returns zero upon success.
*/
int file_rename(
  const char *zFrom,
................................................................................
  char *z = fossil_utf8_to_path(zFilename, 0);
  rc = unlink(zFilename);
#endif
  fossil_path_free(z);
  return rc;
}

/* SQL Function:  file_delete(NAME)
**
** Remove file NAME.  Return zero on success and non-zero if anything goes
** wrong.
*/
void file_delete_sql_function(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName = (const char*)sqlite3_value_text(argv[0]);
  int rc;
  if( zName==0 ){
    rc = 1;
  }else{
    rc = file_delete(zName);
  }
  sqlite3_result_int(context, rc);
}

/*
** Create a directory called zName, if it does not already exist.
** If forceFlag is 1, delete any prior non-directory object
** with the same name.
**
** Return the number of errors.
*/
................................................................................
#endif
    fossil_path_free(zMbcs);
    return rc;
  }
  return 0;
}

/* SQL Function: rmdir(NAME)
**
** Try to remove the directory NAME.  Return zero on success and non-zero
** for failure.
*/
void file_rmdir_sql_function(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zName = (const char*)sqlite3_value_text(argv[0]);
  int rc;
  if( zName==0 ){
    rc = 1;
  }else{
    rc = file_rmdir(zName);
  }
  sqlite3_result_int(context, rc);
}

/*
** Return true if the filename given is a valid filename for
** a file in a repository.  Valid filenames follow all of the
** following rules:
**
**     *  Does not begin with "/"
**     *  Does not contain any path element named "." or ".."
................................................................................

/*
** Get the current working directory.
**
** On windows, the name is converted from unicode to UTF8 and all '\\'
** characters are converted to '/'.  No conversions are needed on
** unix.
**
** Store the value of the CWD in zBuf which is nBuf bytes in size.
** or if zBuf==0, allocate space to hold the result using fossil_malloc().
*/
char *file_getcwd(char *zBuf, int nBuf){
  char zTemp[2000];
  if( zBuf==0 ){
    zBuf = zTemp;
    nBuf = sizeof(zTemp);
  }
#ifdef _WIN32
  win32_getcwd(zBuf, nBuf);
#else
  if( getcwd(zBuf, nBuf-1)==0 ){
    if( errno==ERANGE ){
      fossil_panic("pwd too big: max %d", nBuf-1);
    }else{
      fossil_panic("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif
  return zBuf==zTemp ? fossil_strdup(zBuf) : zBuf;
}

/*
** Return true if zPath is an absolute pathname.  Return false
** if it is relative.
*/
int file_is_absolute_path(const char *zPath){







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<

|
<
<
<
<
<












<







435
436
437
438
439
440
441



















442
443
444
445
446
447
448
...
593
594
595
596
597
598
599




















600
601
602
603
604
605
606
...
683
684
685
686
687
688
689




















690
691
692
693
694
695
696
...
888
889
890
891
892
893
894



895
896





897
898
899
900
901
902
903
904
905
906
907
908

909
910
911
912
913
914
915
  const char *zTail = file_tail(z);
  if( zTail && zTail!=z ){
    return mprintf("%.*s", (int)(zTail-z-1), z);
  }else{
    return 0;
  }
}




















/*
** Rename a file or directory.
** Returns zero upon success.
*/
int file_rename(
  const char *zFrom,
................................................................................
  char *z = fossil_utf8_to_path(zFilename, 0);
  rc = unlink(zFilename);
#endif
  fossil_path_free(z);
  return rc;
}





















/*
** Create a directory called zName, if it does not already exist.
** If forceFlag is 1, delete any prior non-directory object
** with the same name.
**
** Return the number of errors.
*/
................................................................................
#endif
    fossil_path_free(zMbcs);
    return rc;
  }
  return 0;
}





















/*
** Return true if the filename given is a valid filename for
** a file in a repository.  Valid filenames follow all of the
** following rules:
**
**     *  Does not begin with "/"
**     *  Does not contain any path element named "." or ".."
................................................................................

/*
** Get the current working directory.
**
** On windows, the name is converted from unicode to UTF8 and all '\\'
** characters are converted to '/'.  No conversions are needed on
** unix.



*/
void file_getcwd(char *zBuf, int nBuf){





#ifdef _WIN32
  win32_getcwd(zBuf, nBuf);
#else
  if( getcwd(zBuf, nBuf-1)==0 ){
    if( errno==ERANGE ){
      fossil_panic("pwd too big: max %d", nBuf-1);
    }else{
      fossil_panic("cannot find current working directory; %s",
                   strerror(errno));
    }
  }
#endif

}

/*
** Return true if zPath is an absolute pathname.  Return false
** if it is relative.
*/
int file_is_absolute_path(const char *zPath){

Changes to src/http_ssl.c.

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  }

  /* Set the Global.zIpAddr variable to the server we are talking to.
  ** This is used to populate the ipaddr column of the rcvfrom table,
  ** if any files are received from the server.
  */
  {
#ifdef HAVE_BIO_ADDR_HS
    char *ip = BIO_ADDR_hostname_string(BIO_get_conn_address(iBio),1);
    g.zIpAddr = mprintf("%s", ip);
    OPENSSL_free(ip);
#else
    /* IPv4 only code */
    const unsigned char *ip;
    ip = (const unsigned char*)BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
    g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
#endif
  }

  X509_free(cert);
  return 0;
}

/*







<
<
<
<
<

<
|

<







385
386
387
388
389
390
391





392

393
394

395
396
397
398
399
400
401
  }

  /* Set the Global.zIpAddr variable to the server we are talking to.
  ** This is used to populate the ipaddr column of the rcvfrom table,
  ** if any files are received from the server.
  */
  {





    /* IPv4 only code */

    const unsigned char *ip = (const unsigned char *) BIO_ptr_ctrl(iBio,BIO_C_GET_CONNECT,2);
    g.zIpAddr = mprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);

  }

  X509_free(cert);
  return 0;
}

/*

Changes to src/info.c.

1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
....
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
....
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
....
1754
1755
1756
1757
1758
1759
1760


1761
1762
1763
1764
1765
1766
1767
....
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
....
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
....
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
....
2224
2225
2226
2227
2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
....
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
#define OBJTYPE_FORUM      0x0200

/*
** Possible flags for the second parameter to
** object_description()
*/
#define OBJDESC_DETAIL      0x0001   /* more detail */
#define OBJDESC_BASE        0x0002   /* Set <base> using this object */
#endif

/*
** Write a description of an object to the www reply.
**
** If the object is a file then mention:
**
................................................................................
  Stmt q;
  int cnt = 0;
  int nWiki = 0;
  int objType = 0;
  char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  int showDetail = (objdescFlags & OBJDESC_DETAIL)!=0;
  char *prevName = 0;
  int bNeedBase = (objdescFlags & OBJDESC_BASE)!=0;

  db_prepare(&q,
    "SELECT filename.name, datetime(event.mtime,toLocal()),"
    "       coalesce(event.ecomment,event.comment),"
    "       coalesce(event.euser,event.user),"
    "       b.uuid, mlink.mperm,"
    "       coalesce((SELECT value FROM tagxref"
................................................................................
        @ <li>Symbolic link
        objType |= OBJTYPE_SYMLINK;
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
        objType |= OBJTYPE_EXE;
      }else{
        @ <li>File
        if( bNeedBase ){
          bNeedBase = 0;
          style_set_current_page("doc/%S/%s",zVers,zName);
        }
      }
      objType |= OBJTYPE_CONTENT;
      @ %z(href("%R/finfo?name=%T&m=%!S",zName,zUuid))%h(zName)</a>
      tag_private_status(rid);
      if( showDetail ){
        @ <ul>
      }
................................................................................
**
** Return the uninterpreted content of an artifact.  Used primarily
** to view artifacts that are images.
*/
void rawartifact_page(void){
  int rid = 0;
  char *zUuid;



  if( P("ci") && P("filename") ){
    rid = artifact_from_ci_and_filename(0, 0);
  }
  if( rid==0 ){
    rid = name_to_rid_www("name");
  }
................................................................................
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  if( rid==0 ) fossil_redirect_home();
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
    g.isConst = 1;
  }
  free(zUuid);
  deliver_artifact(rid, P("m"));
}


/*
** WEBPAGE: secureraw
** URL: /secureraw/HASH?m=TYPE
**
** Return the uninterpreted content of an artifact.  This is similar
** to /raw except in this case the only way to specify the artifact
** is by the full-length SHA1 or SHA3 hash.  Abbreviations are not
** accepted.
*/
void secure_rawartifact_page(void){
  int rid = 0;
  const char *zUuid = PD("name", "");

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q", zUuid);
  if( rid==0 ){
    cgi_set_status(404, "Not Found");
    @ Unknown artifact: "%h(zUuid)"
    return;
  }
  g.isConst = 1;
  deliver_artifact(rid, P("m"));
}


/*
** Generate a verbatim artifact as the result of an HTTP request.
** If zMime is not NULL, use it as the MIME-type.  If zMime is
** NULL, guess at the MIME-type based on the filename
** associated with the artifact.
*/
void deliver_artifact(int rid, const char *zMime){
  Blob content;
  if( zMime==0 ){
    char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
                              " WHERE mlink.fid=%d"
                              "   AND filename.fnid=mlink.fnid", rid);
    if( !zFName ){
      /* Look also at the attachment table */
      zFName = db_text(0, "SELECT attachment.filename FROM attachment, blob"
................................................................................
  const char *zMime;
  Blob downloadName;
  int renderAsWiki = 0;
  int renderAsHtml = 0;
  int objType;
  int asText;
  const char *zUuid;
  u32 objdescFlags = OBJDESC_BASE;
  int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
  int isFile = fossil_strcmp(g.zPath,"file")==0;
  const char *zLn = P("ln");
  const char *zName = P("name");
  HQuery url;

  url_initialize(&url, g.zPath);
................................................................................
    style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
  }else if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);
  asText = P("txt")!=0;
  if( asText ) objdescFlags &= ~OBJDESC_BASE;
  objType = object_description(rid, objdescFlags, &downloadName);
  if( !descOnly && P("download")!=0 ){
    cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
          db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
    /*NOTREACHED*/
  }
  if( g.perm.Admin ){
................................................................................
    db_finalize(&q);
  }
  style_submenu_element("Download", "%R/raw/%T?name=%s",
                         blob_str(&downloadName), zUuid);
  if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
    style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
  }

  zMime = mimetype_from_name(blob_str(&downloadName));
  if( zMime ){
    if( fossil_strcmp(zMime, "text/html")==0 ){
      if( asText ){
        style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0));
      }else{
        renderAsHtml = 1;
................................................................................
          output_text_with_line_numbers(z, zLn);
        }else{
          @ <pre>
          @ %h(z)
          @ </pre>
        }
      }else if( strncmp(zMime, "image/", 6)==0 ){
        @ <p>(file is %d(blob_size(&content)) bytes of image data)</i></p>
        @ <p><img src="%R/raw/%s(zUuid)?m=%s(zMime)"></p>
        style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime);
      }else{
        @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
      }
      @ </blockquote>
    }
  }







<







 







<







 







<
<
<
<







 







>
>







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







<
<







 







>







 







|
|







1323
1324
1325
1326
1327
1328
1329

1330
1331
1332
1333
1334
1335
1336
....
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
....
1400
1401
1402
1403
1404
1405
1406




1407
1408
1409
1410
1411
1412
1413
....
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
....
1765
1766
1767
1768
1769
1770
1771
1772





































1773
1774
1775
1776
1777
1778
1779
....
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
....
2143
2144
2145
2146
2147
2148
2149


2150
2151
2152
2153
2154
2155
2156
....
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
....
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
#define OBJTYPE_FORUM      0x0200

/*
** Possible flags for the second parameter to
** object_description()
*/
#define OBJDESC_DETAIL      0x0001   /* more detail */

#endif

/*
** Write a description of an object to the www reply.
**
** If the object is a file then mention:
**
................................................................................
  Stmt q;
  int cnt = 0;
  int nWiki = 0;
  int objType = 0;
  char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  int showDetail = (objdescFlags & OBJDESC_DETAIL)!=0;
  char *prevName = 0;


  db_prepare(&q,
    "SELECT filename.name, datetime(event.mtime,toLocal()),"
    "       coalesce(event.ecomment,event.comment),"
    "       coalesce(event.euser,event.user),"
    "       b.uuid, mlink.mperm,"
    "       coalesce((SELECT value FROM tagxref"
................................................................................
        @ <li>Symbolic link
        objType |= OBJTYPE_SYMLINK;
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
        objType |= OBJTYPE_EXE;
      }else{
        @ <li>File




      }
      objType |= OBJTYPE_CONTENT;
      @ %z(href("%R/finfo?name=%T&m=%!S",zName,zUuid))%h(zName)</a>
      tag_private_status(rid);
      if( showDetail ){
        @ <ul>
      }
................................................................................
**
** Return the uninterpreted content of an artifact.  Used primarily
** to view artifacts that are images.
*/
void rawartifact_page(void){
  int rid = 0;
  char *zUuid;
  const char *zMime;
  Blob content;

  if( P("ci") && P("filename") ){
    rid = artifact_from_ci_and_filename(0, 0);
  }
  if( rid==0 ){
    rid = name_to_rid_www("name");
  }
................................................................................
  if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
  if( rid==0 ) fossil_redirect_home();
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( fossil_strcmp(P("name"), zUuid)==0 && login_is_nobody() ){
    g.isConst = 1;
  }
  free(zUuid);
  zMime = P("m");





































  if( zMime==0 ){
    char *zFName = db_text(0, "SELECT filename.name FROM mlink, filename"
                              " WHERE mlink.fid=%d"
                              "   AND filename.fnid=mlink.fnid", rid);
    if( !zFName ){
      /* Look also at the attachment table */
      zFName = db_text(0, "SELECT attachment.filename FROM attachment, blob"
................................................................................
  const char *zMime;
  Blob downloadName;
  int renderAsWiki = 0;
  int renderAsHtml = 0;
  int objType;
  int asText;
  const char *zUuid;
  u32 objdescFlags = 0;
  int descOnly = fossil_strcmp(g.zPath,"whatis")==0;
  int isFile = fossil_strcmp(g.zPath,"file")==0;
  const char *zLn = P("ln");
  const char *zName = P("name");
  HQuery url;

  url_initialize(&url, g.zPath);
................................................................................
    style_submenu_element("Artifact", "%R/artifact/%S", zUuid);
  }else if( g.perm.Setup ){
    @ <h2>Artifact %s(zUuid) (%d(rid)):</h2>
  }else{
    @ <h2>Artifact %s(zUuid):</h2>
  }
  blob_zero(&downloadName);


  objType = object_description(rid, objdescFlags, &downloadName);
  if( !descOnly && P("download")!=0 ){
    cgi_redirectf("%R/raw/%T?name=%s", blob_str(&downloadName),
          db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid));
    /*NOTREACHED*/
  }
  if( g.perm.Admin ){
................................................................................
    db_finalize(&q);
  }
  style_submenu_element("Download", "%R/raw/%T?name=%s",
                         blob_str(&downloadName), zUuid);
  if( db_exists("SELECT 1 FROM mlink WHERE fid=%d", rid) ){
    style_submenu_element("Check-ins Using", "%R/timeline?n=200&uf=%s", zUuid);
  }
  asText = P("txt")!=0;
  zMime = mimetype_from_name(blob_str(&downloadName));
  if( zMime ){
    if( fossil_strcmp(zMime, "text/html")==0 ){
      if( asText ){
        style_submenu_element("Html", "%s", url_render(&url, "txt", 0, 0, 0));
      }else{
        renderAsHtml = 1;
................................................................................
          output_text_with_line_numbers(z, zLn);
        }else{
          @ <pre>
          @ %h(z)
          @ </pre>
        }
      }else if( strncmp(zMime, "image/", 6)==0 ){
        @ <i>(file is %d(blob_size(&content)) bytes of image data)</i><br />
        @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" />
        style_submenu_element("Image", "%R/raw/%s?m=%s", zUuid, zMime);
      }else{
        @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
      }
      @ </blockquote>
    }
  }

Changes to src/login.c.

695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
  }
  if( anonFlag ){
    @ <input type="hidden" name="anon" value="1" />
  }
  if( g.zLogin ){
    @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
    @ <input type="submit" name="out" value="Logout"></p>
    @ </form>
  }else{
    @ <table class="login_out">
    @ <tr>
    @   <td class="form_label">User ID:</td>
    if( anonFlag ){
      @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
    }else{







<







695
696
697
698
699
700
701

702
703
704
705
706
707
708
  }
  if( anonFlag ){
    @ <input type="hidden" name="anon" value="1" />
  }
  if( g.zLogin ){
    @ <p>Currently logged in as <b>%h(g.zLogin)</b>.
    @ <input type="submit" name="out" value="Logout"></p>

  }else{
    @ <table class="login_out">
    @ <tr>
    @   <td class="form_label">User ID:</td>
    if( anonFlag ){
      @ <td><input type="text" id="u" name="u" value="anonymous" size="30"></td>
    }else{

Changes to src/main.c.

2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }
  /* For the parent process, the cgi_http_server() command above never
  ** returns (except in the case of an error).  Instead, for each incoming
  ** client connection, a child process is created, file descriptors 0
  ** and 1 are bound to that connection, and the child returns.
  **
  ** So, when control reaches this point, we are running as a
  ** child process, the HTTP or SCGI request is pending on file
  ** descriptor 0 and the reply should be written to file descriptor 1.
  */
  if( zMaxLatency ){
    signal(SIGALRM, sigalrm_handler);
    alarm(atoi(zMaxLatency));
  }
  g.httpIn = stdin;
  g.httpOut = stdout;








<
<
<
<
<
<
<
<
<







2637
2638
2639
2640
2641
2642
2643









2644
2645
2646
2647
2648
2649
2650
  }
  if( g.repositoryOpen ) flags |= HTTP_SERVER_HAD_REPOSITORY;
  if( g.localOpen ) flags |= HTTP_SERVER_HAD_CHECKOUT;
  db_close(1);
  if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
    fossil_fatal("unable to listen on TCP socket %d", iPort);
  }









  if( zMaxLatency ){
    signal(SIGALRM, sigalrm_handler);
    alarm(atoi(zMaxLatency));
  }
  g.httpIn = stdin;
  g.httpOut = stdout;

Changes to src/main.mk.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
....
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/deltafunc.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/deltafunc_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/deltafunc.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................

APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)

install:	all
	mkdir -p $(INSTALLDIR)
	cp $(APPNAME) $(INSTALLDIR)

codecheck:	$(TRANS_SRC) $(OBJDIR)/codecheck1
	$(OBJDIR)/codecheck1 $(TRANS_SRC)

$(OBJDIR):
................................................................................
	$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
	$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
	$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
	$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
	$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
	$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
	$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
	$(OBJDIR)/deltafunc_.c:$(OBJDIR)/deltafunc.h \
	$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
	$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
	$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
	$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
	$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(OBJDIR)/translate $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/deltafunc_.c:	$(SRCDIR)/deltafunc.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/deltafunc.c >$@

$(OBJDIR)/deltafunc.o:	$(OBJDIR)/deltafunc_.c $(OBJDIR)/deltafunc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltafunc.o -c $(OBJDIR)/deltafunc_.c

$(OBJDIR)/deltafunc.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers







<







 







<







 







<







 







|







 







<







 







<
<
<
<
<
<
<
<







39
40
41
42
43
44
45

46
47
48
49
50
51
52
...
250
251
252
253
254
255
256

257
258
259
260
261
262
263
...
388
389
390
391
392
393
394

395
396
397
398
399
400
401
...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
...
722
723
724
725
726
727
728

729
730
731
732
733
734
735
....
1054
1055
1056
1057
1058
1059
1060








1061
1062
1063
1064
1065
1066
1067
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \

  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \

  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \

 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................

APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)
	mkdir -p $(INSTALLDIR)
	cp $(APPNAME) $(INSTALLDIR)

codecheck:	$(TRANS_SRC) $(OBJDIR)/codecheck1
	$(OBJDIR)/codecheck1 $(TRANS_SRC)

$(OBJDIR):
................................................................................
	$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
	$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
	$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
	$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
	$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
	$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
	$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \

	$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
	$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
	$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
	$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
	$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(OBJDIR)/translate $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers









$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

Changes to src/makemake.tcl.

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
....
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
  comformat
  configure
  content
  cookies
  db
  delta
  deltacmd
  deltafunc
  descendants
  diff
  diffcmd
  dispatch
  doc
  encode
  etag
................................................................................

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n                 "] \
    <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n                "] \
    <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n                "]] {
all:	$(OBJDIR) $(APPNAME)

install:	all
	mkdir -p $(INSTALLDIR)
	cp $(APPNAME) $(INSTALLDIR)

codecheck:	$(TRANS_SRC) $(OBJDIR)/codecheck1
	$(OBJDIR)/codecheck1 $(TRANS_SRC)

$(OBJDIR):
................................................................................
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2r
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................

# Enable support for the SQLite Encryption Extension?
!ifndef USE_SEE
USE_SEE = 0
!endif

!if $(FOSSIL_ENABLE_SSL)!=0
SSLDIR    = $(B)\compat\openssl-1.0.2r
SSLINCDIR = $(SSLDIR)\inc32
!if $(FOSSIL_DYNAMIC_BUILD)!=0
SSLLIBDIR = $(SSLDIR)\out32dll
!else
SSLLIBDIR = $(SSLDIR)\out32
!endif
SSLLFLAGS = /nologo /opt:ref /debug







<







 







|







 







|







 







|







50
51
52
53
54
55
56

57
58
59
60
61
62
63
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
....
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
  comformat
  configure
  content
  cookies
  db
  delta
  deltacmd

  descendants
  diff
  diffcmd
  dispatch
  doc
  encode
  etag
................................................................................

writeln [string map [list \
    <<<SQLITE_OPTIONS>>> [join $SQLITE_OPTIONS " \\\n                 "] \
    <<<SHELL_OPTIONS>>> [join $SHELL_OPTIONS " \\\n                "] \
    <<<MINIZ_OPTIONS>>> [join $MINIZ_OPTIONS " \\\n                "]] {
all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)
	mkdir -p $(INSTALLDIR)
	cp $(APPNAME) $(INSTALLDIR)

codecheck:	$(TRANS_SRC) $(OBJDIR)/codecheck1
	$(OBJDIR)/codecheck1 $(TRANS_SRC)

$(OBJDIR):
................................................................................
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2q
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................

# Enable support for the SQLite Encryption Extension?
!ifndef USE_SEE
USE_SEE = 0
!endif

!if $(FOSSIL_ENABLE_SSL)!=0
SSLDIR    = $(B)\compat\openssl-1.0.2q
SSLINCDIR = $(SSLDIR)\inc32
!if $(FOSSIL_DYNAMIC_BUILD)!=0
SSLLIBDIR = $(SSLDIR)\out32dll
!else
SSLLIBDIR = $(SSLDIR)\out32
!endif
SSLLFLAGS = /nologo /opt:ref /debug

Changes to src/printf.c.

963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
    Blob b = empty_blob;
    vxprintf(&b, zFormat, ap);
    fossil_puts(blob_str(&b), 0);
    blob_reset(&b);
  }
  va_end(ap);
}
void fossil_vprint(const char *zFormat, va_list ap){
  if( g.cgiOutput ){
    cgi_vprintf(zFormat, ap);
  }else{
    Blob b = empty_blob;
    vxprintf(&b, zFormat, ap);
    fossil_puts(blob_str(&b), 0);
    blob_reset(&b);
  }
}

/*
** Print a trace message on standard error.
*/
void fossil_trace(const char *zFormat, ...){
  va_list ap;
  Blob b;







<
<
<
<
<
<
<
<
<
<







963
964
965
966
967
968
969










970
971
972
973
974
975
976
    Blob b = empty_blob;
    vxprintf(&b, zFormat, ap);
    fossil_puts(blob_str(&b), 0);
    blob_reset(&b);
  }
  va_end(ap);
}











/*
** Print a trace message on standard error.
*/
void fossil_trace(const char *zFormat, ...){
  va_list ap;
  Blob b;

Changes to src/regexp.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696







697
698
699
700
701
702
703
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file was adapted from the ext/misc/regexp.c file in SQLite3.  That
** file is in the public domain.
**
** See ../www/grep.md for details of the algorithm and RE dialect.
*/
#include "config.h"
#include "regexp.h"

................................................................................
};
#endif

/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
  unsigned i;
  for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
  pSet->aState[pSet->nState++] = (ReStateNumber)newState;
}

/* Extract the next unicode character from *pzIn and return it.  Advance
** *pzIn to the first byte past the end of the character returned.  To
** be clear:  this routine converts utf8 to unicode.  This routine is
** optimized for the common case where the next character is a single byte.
*/
................................................................................
      c = 0xfffd;
    }
  }
  return c;
}
static unsigned re_next_char_nocase(ReInput *p){
  unsigned c = re_next_char(p);
  return unicode_fold(c,2);
}

/* Return true if c is a perl "word" character:  [A-Za-z0-9_] */
static int re_word_char(int c){
  return unicode_isalnum(c) || c=='_';
}

................................................................................
  int c = RE_EOF+1;
  int cPrev = 0;
  int rc = 0;
  ReInput in;

  in.z = zIn;
  in.i = 0;
  in.mx = nIn>=0 ? nIn : (int)strlen((char const*)zIn);

  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( in.i+pRe->nInit<=in.mx
     && (zIn[in.i]!=x ||
         strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
    ){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
  }

  if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
    pToFree = 0;
    aStateSet[0].aState = aSpace;
  }else{
    pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState );
    if( pToFree==0 ) return -1;
    aStateSet[0].aState = pToFree;
  }
................................................................................
  int i;
  if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
  for(i=p->nState; i>iBefore; i--){
    p->aOp[i] = p->aOp[i-1];
    p->aArg[i] = p->aArg[i-1];
  }
  p->nState++;
  p->aOp[iBefore] = (char)op;
  p->aArg[iBefore] = arg;
  return iBefore;
}

/* Append a new opcode and argument to the end of the RE under construction.
*/
static int re_append(ReCompiled *p, int op, int arg){
................................................................................
  if( zIn[0]=='^' ){
    zIn++;
  }else{
    re_append(pRe, RE_OP_ANYSTAR, 0);
  }
  pRe->sIn.z = (unsigned char*)zIn;
  pRe->sIn.i = 0;
  pRe->sIn.mx = (int)strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
    return zErr;
  }
  if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_MATCH, RE_EOF);
................................................................................
  ** regex engine over the string.  Do not worry able trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */
  if( pRe->aOp[0]==RE_OP_ANYSTAR ){
    for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=127 ){
        pRe->zInit[j++] = (unsigned char)x;
      }else if( x<=0xfff ){
        pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
        pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
        pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else{
        break;
      }
    }
    if( j>0 && pRe->zInit[j-1]==0 ) j--;
................................................................................
  int argc,
  sqlite3_value **argv
){
  ReCompiled *pRe;          /* Compiled regular expression */
  const char *zPattern;     /* The regular expression */
  const unsigned char *zStr;/* String being searched */
  const char *zErr;         /* Compile error message */
  int setAux = 0;           /* True to invoke sqlite3_set_auxdata() */

  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    zPattern = (const char*)sqlite3_value_text(argv[0]);
    if( zPattern==0 ) return;
    zErr = re_compile(&pRe, zPattern, 0);
    if( zErr ){
      re_free(pRe);
      sqlite3_result_error(context, zErr, -1);
      return;
    }
    if( pRe==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    setAux = 1;
  }
  zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }
  if( setAux ){
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
}

/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.







*/
int re_add_sql_func(sqlite3 *db){
  return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
                                 re_sql_func, 0, 0);
}

/*







|







 







|







 







|







 







|













|







 







|







 







|







 







|

|


|







 







<







<







|





<
<
<



|

>
>
>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
...
660
661
662
663
664
665
666

667
668
669
670
671
672
673

674
675
676
677
678
679
680
681
682
683
684
685
686



687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file was adapted from the test_regexp.c file in SQLite3.  That
** file is in the public domain.
**
** See ../www/grep.md for details of the algorithm and RE dialect.
*/
#include "config.h"
#include "regexp.h"

................................................................................
};
#endif

/* Add a state to the given state set if it is not already there */
static void re_add_state(ReStateSet *pSet, int newState){
  unsigned i;
  for(i=0; i<pSet->nState; i++) if( pSet->aState[i]==newState ) return;
  pSet->aState[pSet->nState++] = newState;
}

/* Extract the next unicode character from *pzIn and return it.  Advance
** *pzIn to the first byte past the end of the character returned.  To
** be clear:  this routine converts utf8 to unicode.  This routine is
** optimized for the common case where the next character is a single byte.
*/
................................................................................
      c = 0xfffd;
    }
  }
  return c;
}
static unsigned re_next_char_nocase(ReInput *p){
  unsigned c = re_next_char(p);
  return unicode_fold(c,1);
}

/* Return true if c is a perl "word" character:  [A-Za-z0-9_] */
static int re_word_char(int c){
  return unicode_isalnum(c) || c=='_';
}

................................................................................
  int c = RE_EOF+1;
  int cPrev = 0;
  int rc = 0;
  ReInput in;

  in.z = zIn;
  in.i = 0;
  in.mx = nIn>=0 ? nIn : strlen((const char*)zIn);

  /* Look for the initial prefix match, if there is one. */
  if( pRe->nInit ){
    unsigned char x = pRe->zInit[0];
    while( in.i+pRe->nInit<=in.mx
     && (zIn[in.i]!=x ||
         strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
    ){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
  }

  if( pRe->nState<=count(aSpace)*2 ){
    pToFree = 0;
    aStateSet[0].aState = aSpace;
  }else{
    pToFree = fossil_malloc( sizeof(ReStateNumber)*2*pRe->nState );
    if( pToFree==0 ) return -1;
    aStateSet[0].aState = pToFree;
  }
................................................................................
  int i;
  if( p->nAlloc<=p->nState && re_resize(p, p->nAlloc*2) ) return 0;
  for(i=p->nState; i>iBefore; i--){
    p->aOp[i] = p->aOp[i-1];
    p->aArg[i] = p->aArg[i-1];
  }
  p->nState++;
  p->aOp[iBefore] = op;
  p->aArg[iBefore] = arg;
  return iBefore;
}

/* Append a new opcode and argument to the end of the RE under construction.
*/
static int re_append(ReCompiled *p, int op, int arg){
................................................................................
  if( zIn[0]=='^' ){
    zIn++;
  }else{
    re_append(pRe, RE_OP_ANYSTAR, 0);
  }
  pRe->sIn.z = (unsigned char*)zIn;
  pRe->sIn.i = 0;
  pRe->sIn.mx = strlen(zIn);
  zErr = re_subcompile_re(pRe);
  if( zErr ){
    re_free(pRe);
    return zErr;
  }
  if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_MATCH, RE_EOF);
................................................................................
  ** regex engine over the string.  Do not worry able trying to match
  ** unicode characters beyond plane 0 - those are very rare and this is
  ** just an optimization. */
  if( pRe->aOp[0]==RE_OP_ANYSTAR ){
    for(j=0, i=1; j<sizeof(pRe->zInit)-2 && pRe->aOp[i]==RE_OP_MATCH; i++){
      unsigned x = pRe->aArg[i];
      if( x<=127 ){
        pRe->zInit[j++] = x;
      }else if( x<=0xfff ){
        pRe->zInit[j++] = 0xc0 | (x>>6);
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else if( x<=0xffff ){
        pRe->zInit[j++] = 0xd0 | (x>>12);
        pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
        pRe->zInit[j++] = 0x80 | (x&0x3f);
      }else{
        break;
      }
    }
    if( j>0 && pRe->zInit[j-1]==0 ) j--;
................................................................................
  int argc,
  sqlite3_value **argv
){
  ReCompiled *pRe;          /* Compiled regular expression */
  const char *zPattern;     /* The regular expression */
  const unsigned char *zStr;/* String being searched */
  const char *zErr;         /* Compile error message */


  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    zPattern = (const char*)sqlite3_value_text(argv[0]);
    if( zPattern==0 ) return;
    zErr = re_compile(&pRe, zPattern, 0);
    if( zErr ){

      sqlite3_result_error(context, zErr, -1);
      return;
    }
    if( pRe==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    sqlite3_set_auxdata(context, 0, pRe, (void(*)(void*))re_free);
  }
  zStr = (const unsigned char*)sqlite3_value_text(argv[1]);
  if( zStr!=0 ){
    sqlite3_result_int(context, re_match(pRe, zStr, -1));
  }



}

/*
** Invoke this routine in order to install the REGEXP function in an
** SQLite database connection.
**
** Use:
**
**      sqlite3_auto_extension(sqlite3_add_regexp_func);
**
** to cause this extension to be automatically loaded into each new
** database connection.
*/
int re_add_sql_func(sqlite3 *db){
  return sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8, 0,
                                 re_sql_func, 0, 0);
}

/*

Changes to src/security_audit.c.

286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
    @ <li><p>
    @ Users with administrator privilege are: %s(z)
    fossil_free(z);
    if( n>3 ){
      @ <li><p><b>WARNING:</b>
      @ Administrator privilege is granted to
      @ <a href='setup_ulist?with=as'>%d(n) users</a>.
      @ Ideally, administrator privilege ('s' or 'a') should only
      @ be granted to one or two users.
    }
  }

  /* The push-unversioned privilege should only be provided to
  ** specific individuals, not to entire classes of people.
  ** And no too many people should have this privilege.







|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
    @ <li><p>
    @ Users with administrator privilege are: %s(z)
    fossil_free(z);
    if( n>3 ){
      @ <li><p><b>WARNING:</b>
      @ Administrator privilege is granted to
      @ <a href='setup_ulist?with=as'>%d(n) users</a>.
      @ Ideally, administator privilege ('s' or 'a') should only
      @ be granted to one or two users.
    }
  }

  /* The push-unversioned privilege should only be provided to
  ** specific individuals, not to entire classes of people.
  ** And no too many people should have this privilege.

Changes to src/shell.c.

2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
.....
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
.....
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751
.....
10786
10787
10788
10789
10790
10791
10792
10793


10794
10795
10796


10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812
10813
10814
10815
.....
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
.....
14771
14772
14773
14774
14775
14776
14777
14778
14779
14780
14781
14782
14783
14784
14785
14786
14787
14788
14789
14790
14791
14792
14793
14794
14795
14796
14797
14798
14799
14800
14801
14802
14803
14804
14805
14806
14807
14808
14809
14810
14811
14812
14813
14814
14815
14816
14817
14818
14819
14820
14821
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14843
14844
14845
14846
14847
14848
14849
14850
14851
14852
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
  db = sqlite3_context_db_handle(ctx);
  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
  if( nIn>mxBlob ){
    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
    fclose(in);
    return;
  }
  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
  if( pBuf==0 ){
    sqlite3_result_error_nomem(ctx);
    fclose(in);
    return;
  }
  if( nIn==fread(pBuf, 1, nIn, in) ){
    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
  }else{
    sqlite3_result_error_code(ctx, SQLITE_IOERR);
    sqlite3_free(pBuf);
  }
  fclose(in);
}
................................................................................
  sqlite3SelectTrace = savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  sqlite3WhereTrace = savedWhereTrace;
#endif
}

/* Name of the TEMP table that holds bind parameter values */
#define BIND_PARAM_TABLE "$Parameters"

/* Create the TEMP table used to store parameter bindings */
static void bind_table_init(ShellState *p){
  sqlite3_exec(p->db,
    "CREATE TABLE IF NOT EXISTS temp.[" BIND_PARAM_TABLE "](\n"
    "  key TEXT PRIMARY KEY,\n"
    "  value ANY\n"
    ") WITHOUT ROWID;",
    0, 0, 0);
}

/*
** Bind parameters on a prepared statement.
**
** Parameter bindings are taken from a TEMP table of the form:
**
**    CREATE TEMP TABLE "$Parameters"(key TEXT PRIMARY KEY, value)
**    WITHOUT ROWID;
**
** No bindings occur if this table does not exist.  The special character '$'
** is included in the table name to help prevent collisions with actual tables.
** The table must be in the TEMP schema.
*/
static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
  int nVar;
  int i;
  int rc;
  sqlite3_stmt *pQ = 0;

  nVar = sqlite3_bind_parameter_count(pStmt);
  if( nVar==0 ) return;  /* Nothing to do */
  if( sqlite3_table_column_metadata(pArg->db, "TEMP", BIND_PARAM_TABLE,
                                    "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
    return; /* Parameter table does not exist */
  }
  rc = sqlite3_prepare_v2(pArg->db,
          "SELECT value FROM temp.\"" BIND_PARAM_TABLE "\""
          " WHERE key=?1", -1, &pQ, 0);
  if( rc || pQ==0 ) return;
  for(i=1; i<=nVar; i++){
    char zNum[30];
    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
    if( zVar==0 ){
      sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
      zVar = zNum;
    }
    sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
    if( sqlite3_step(pQ)==SQLITE_ROW ){
      sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
    }else{
      sqlite3_bind_null(pStmt, i);
    }
    sqlite3_reset(pQ);
  }
  sqlite3_finalize(pQ);
}

/*
** Run a prepared statement
*/
static void exec_prepared_stmt(
  ShellState *pArg,                                /* Pointer to ShellState */
  sqlite3_stmt *pStmt                              /* Statment to run */
){
................................................................................

      /* echo the sql statement if echo on */
      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
      }

      /* Show the EXPLAIN QUERY PLAN if .eqp is on */
      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
        sqlite3_stmt *pExplain;
        char *zEQP;
        int triggerEQP = 0;
        disable_debug_trace_modes();
        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
        if( pArg->autoEQP>=AUTOEQP_trigger ){
          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
................................................................................
        }
        restore_debug_trace_modes();
      }

      if( pArg ){
        pArg->cMode = pArg->mode;
        if( pArg->autoExplain ){
          if( sqlite3_stmt_isexplain(pStmt)==1 ){


            pArg->cMode = MODE_Explain;
          }
          if( sqlite3_stmt_isexplain(pStmt)==2 ){


            pArg->cMode = MODE_EQP;
          }
        }

        /* If the shell is currently in ".explain" mode, gather the extra
        ** data required to add indents to the output.*/
        if( pArg->cMode==MODE_Explain ){
          explain_data_prepare(pArg, pStmt);
        }
      }

      bind_prepared_stmt(pArg, pStmt);
      exec_prepared_stmt(pArg, pStmt);
      explain_data_delete(pArg);
      eqp_render(pArg);

      /* print usage stats if stats on */
      if( pArg && pArg->statsOn ){
        display_stats(db, pArg, 0);
................................................................................
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",
  ".parameter CMD ...       Manage SQL parameter bindings",
  "   clear                   Erase all bindings",
  "   init                    Initialize the TEMP table that holds bindings",
  "   list                    List the current parameter bindings",
  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
  "                           PARAMETER should start with '$', ':', '@', or '?'",
  "   unset PARAMETER         Remove PARAMETER from the binding table",
  ".print STRING...         Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  ".progress N              Invoke progress handler after every N opcodes",
  "   --limit N                 Interrupt after N progress callbacks",
  "   --once                    Do no more than one progress interrupt",
  "   --quiet|-q                No output except at interrupts",
  "   --reset                   Reset the count for each input and interrupt",
................................................................................
        rc = 1;
      } else {
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
  }else

  if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
    open_db(p,0);
    if( nArg<=1 ) goto parameter_syntax_error;

    /* .parameter clear
    ** Clear all bind parameters by dropping the TEMP table that holds them.
    */
    if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
      sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.[" BIND_PARAM_TABLE "];",
                   0, 0, 0);
    }else

    /* .parameter list
    ** List all bind parameters.
    */
    if( nArg==2 && strcmp(azArg[1],"list")==0 ){
      sqlite3_stmt *pStmt = 0;
      int rx;
      int len = 0;
      rx = sqlite3_prepare_v2(p->db,
             "SELECT max(length(key)) "
             "FROM temp.[" BIND_PARAM_TABLE "];", -1, &pStmt, 0);
      if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
        len = sqlite3_column_int(pStmt, 0);
        if( len>40 ) len = 40;
      }
      sqlite3_finalize(pStmt);
      pStmt = 0;
      if( len ){
        rx = sqlite3_prepare_v2(p->db,
             "SELECT key, quote(value) "
             "FROM temp.[" BIND_PARAM_TABLE "];", -1, &pStmt, 0);
        while( sqlite3_step(pStmt)==SQLITE_ROW ){
          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                      sqlite3_column_text(pStmt,1));
        }
        sqlite3_finalize(pStmt);
      }
    }else

    /* .parameter init
    ** Make sure the TEMP table used to hold bind parameters exists.
    ** Create it if necessary.
    */
    if( nArg==2 && strcmp(azArg[1],"init")==0 ){
      bind_table_init(p);
    }else

    /* .parameter set NAME VALUE
    ** Set or reset a bind parameter.  NAME should be the full parameter
    ** name exactly as it appears in the query.  (ex: $abc, @def).  The
    ** VALUE can be in either SQL literal notation, or if not it will be
    ** understood to be a text string.
    */
    if( nArg==4 && strcmp(azArg[1],"set")==0 ){
      int rx;
      char *zSql;
      sqlite3_stmt *pStmt;
      const char *zKey = azArg[2];
      const char *zValue = azArg[3];
      bind_table_init(p);
      zSql = sqlite3_mprintf(
                  "REPLACE INTO temp.[" BIND_PARAM_TABLE "](key,value)"
                  "VALUES(%Q,%s);", zKey, zValue);
      if( zSql==0 ) shell_out_of_memory();
      pStmt = 0;
      rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      sqlite3_free(zSql);
      if( rx!=SQLITE_OK ){
        sqlite3_finalize(pStmt);
        pStmt = 0;
        zSql = sqlite3_mprintf(
                   "REPLACE INTO temp.[" BIND_PARAM_TABLE "](key,value)"
                   "VALUES(%Q,%Q);", zKey, zValue);
        if( zSql==0 ) shell_out_of_memory();
        rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        sqlite3_free(zSql);
        if( rx!=SQLITE_OK ){
          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          pStmt = 0;
          rc = 1;
        }
      }
      sqlite3_step(pStmt);
      sqlite3_finalize(pStmt);
    }else

    /* .parameter unset NAME
    ** Remove the NAME binding from the parameter binding table, if it
    ** exists.
    */
    if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
      char *zSql = sqlite3_mprintf(
          "DELETE FROM temp.[" BIND_PARAM_TABLE "] WHERE key=%Q", azArg[2]);
      if( zSql==0 ) shell_out_of_memory();
      sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
    }else
    /* If no command name matches, show a syntax error */
    parameter_syntax_error:
    showHelp(p->out, "parameter");
  }else

  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) raw_printf(p->out, " ");
      utf8_printf(p->out, "%s", azArg[i]);
    }
    raw_printf(p->out, "\n");







|





|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|
>
>


<
>
>











<







 







<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
.....
10426
10427
10428
10429
10430
10431
10432



























































10433
10434
10435
10436
10437
10438
10439
.....
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
.....
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738

10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751

10752
10753
10754
10755
10756
10757
10758
.....
11176
11177
11178
11179
11180
11181
11182







11183
11184
11185
11186
11187
11188
11189
.....
14707
14708
14709
14710
14711
14712
14713








































































































14714
14715
14716
14717
14718
14719
14720
  db = sqlite3_context_db_handle(ctx);
  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
  if( nIn>mxBlob ){
    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
    fclose(in);
    return;
  }
  pBuf = sqlite3_malloc64( nIn );
  if( pBuf==0 ){
    sqlite3_result_error_nomem(ctx);
    fclose(in);
    return;
  }
  if( 1==fread(pBuf, nIn, 1, in) ){
    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
  }else{
    sqlite3_result_error_code(ctx, SQLITE_IOERR);
    sqlite3_free(pBuf);
  }
  fclose(in);
}
................................................................................
  sqlite3SelectTrace = savedSelectTrace;
#endif
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
  sqlite3WhereTrace = savedWhereTrace;
#endif
}




























































/*
** Run a prepared statement
*/
static void exec_prepared_stmt(
  ShellState *pArg,                                /* Pointer to ShellState */
  sqlite3_stmt *pStmt                              /* Statment to run */
){
................................................................................

      /* echo the sql statement if echo on */
      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
      }

      /* Show the EXPLAIN QUERY PLAN if .eqp is on */
      if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
        sqlite3_stmt *pExplain;
        char *zEQP;
        int triggerEQP = 0;
        disable_debug_trace_modes();
        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
        if( pArg->autoEQP>=AUTOEQP_trigger ){
          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
................................................................................
        }
        restore_debug_trace_modes();
      }

      if( pArg ){
        pArg->cMode = pArg->mode;
        if( pArg->autoExplain ){
          if( sqlite3_column_count(pStmt)==8
           && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
          ){
            pArg->cMode = MODE_Explain;
          }

          if( sqlite3_column_count(pStmt)==4
           && sqlite3_strlike("EXPLAIN QUERY PLAN%", zStmtSql,0)==0 ){
            pArg->cMode = MODE_EQP;
          }
        }

        /* If the shell is currently in ".explain" mode, gather the extra
        ** data required to add indents to the output.*/
        if( pArg->cMode==MODE_Explain ){
          explain_data_prepare(pArg, pStmt);
        }
      }


      exec_prepared_stmt(pArg, pStmt);
      explain_data_delete(pArg);
      eqp_render(pArg);

      /* print usage stats if stats on */
      if( pArg && pArg->statsOn ){
        display_stats(db, pArg, 0);
................................................................................
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",







  ".print STRING...         Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  ".progress N              Invoke progress handler after every N opcodes",
  "   --limit N                 Interrupt after N progress callbacks",
  "   --once                    Do no more than one progress interrupt",
  "   --quiet|-q                No output except at interrupts",
  "   --reset                   Reset the count for each input and interrupt",
................................................................................
        rc = 1;
      } else {
        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
      }
    }
  }else









































































































  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) raw_printf(p->out, " ");
      utf8_printf(p->out, "%s", azArg[i]);
    }
    raw_printf(p->out, "\n");

Changes to src/sitemap.c.

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    @   <li>%z(href("%R/bloblist"))List of Artifacts</a></li>
    @   <li>%z(href("%R/timewarps"))List of "Timewarp" Check-ins</a></li>
    @   </ul>
    @ </li>
  }
  @ <li>Help
  @   <ul>
  if( g.perm.Admin || g.perm.Write ||
      g.perm.WrForum || g.perm.WrTForum ||
      g.perm.NewWiki || g.perm.ApndWiki || g.perm.WrWiki || g.perm.ModWiki ||
      g.perm.NewTkt  || g.perm.ApndTkt  || g.perm.WrTkt  || g.perm.ModTkt ){
    @   <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
    @   <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>
  }
  @   <li>%z(href("%R/help"))List of All Commands and Web Pages</a></li>
  @   <li>%z(href("%R/test-all-help"))All "help" text on a single page</a></li>
  if( g.perm.Admin || g.perm.Write || g.perm.WrUnver ){
    @   <li>%z(href("%R/mimetype_list"))Filename suffix to MIME type map</a></li>
  }
  @   </ul></li>
  if( g.perm.Admin ){
    @ <li>%z(href("%R/setup"))Administration Pages</a>
    @   <ul>
    @   <li>%z(href("%R/modreq"))Pending Moderation Requests</a></li>
    @   <li>%z(href("%R/admin_log"))Admin log</a></li>
    @   <li>%z(href("%R/cachestat"))Status of the web-page cache</a></li>







<
<
<
<
|
|
<


<
|
<







191
192
193
194
195
196
197




198
199

200
201

202

203
204
205
206
207
208
209
    @   <li>%z(href("%R/bloblist"))List of Artifacts</a></li>
    @   <li>%z(href("%R/timewarps"))List of "Timewarp" Check-ins</a></li>
    @   </ul>
    @ </li>
  }
  @ <li>Help
  @   <ul>




  @   <li>%z(href("%R/wiki_rules"))Wiki Formatting Rules</a></li>
  @   <li>%z(href("%R/md_rules"))Markdown Formatting Rules</a></li>

  @   <li>%z(href("%R/help"))List of All Commands and Web Pages</a></li>
  @   <li>%z(href("%R/test-all-help"))All "help" text on a single page</a></li>

  @   <li>%z(href("%R/mimetype_list"))Filename suffix to mimetype map</a></li>

  @   </ul></li>
  if( g.perm.Admin ){
    @ <li>%z(href("%R/setup"))Administration Pages</a>
    @   <ul>
    @   <li>%z(href("%R/modreq"))Pending Moderation Requests</a></li>
    @   <li>%z(href("%R/admin_log"))Admin log</a></li>
    @   <li>%z(href("%R/cachestat"))Status of the web-page cache</a></li>

Changes to src/sqlcmd.c.

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
  const void *notUsed
){
  add_content_sql_commands(db);
  db_add_aux_functions(db);
  re_add_sql_func(db);
  search_sql_setup(db);
  foci_register(db);
  deltafunc_init(db);
  g.repositoryOpen = 1;
  g.db = db;
  sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
  db_maybe_set_encryption_key(db, g.zRepositoryName);
  if( g.zLocalDbName ){
    char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
                                 g.zLocalDbName);
................................................................................
**
** WARNING:  Careless use of this command can corrupt a Fossil repository
** in ways that are unrecoverable.  Be sure you know what you are doing before
** running any SQL commands that modify the repository database.
**
** The following extensions to the usual SQLite commands are provided:
**
**    checkin_mtime(X,Y)        Return the mtime for the file Y (a BLOB.RID)
**                              found in check-in X (another BLOB.RID value).
**
**    compress(X)               Compress text X.
**
**    content(X)                Return the content of artifact X. X can be an
**                              artifact hash or hash prefix or a tag. Artifacts
**                              are stored compressed and deltaed. This function
**                              does all necessary decompression and undeltaing.
**
**    decompress(X)             Decompress text X.  Undoes the work of
**                              compress(X).
**
**    delta_apply(X,D)          Apply delta D to source blob X and return
**                              the result.
**
**    delta_create(X,Y)         Create and return a delta that will convert
**                              X into Y.
**
**    delta_output_size(D)      Return the number of bytes of output to expect
**                              when applying delta D
**
**    delta_parse(D)            A table-valued function that deconstructs
**                              delta D and returns rows for each element of
**                              that delta.
**
**    files_of_checkin(X)       A table-valued function that returns info on
**                              all files contained in check-in X.  Example:
**                                SELECT * FROM files_of_checkin('trunk');
**
**    now()                     Return the number of seconds since 1970.
**
**    REGEXP                    The REGEXP operator works, unlike in
**                              standard SQLite.
**
**    symbolic_name_to_rid(X)   Return the BLOB.RID corresponding to symbolic

**                              name X.
*/
void cmd_sqlite3(void){
  int noRepository;
  const char *zConfigDb;
  extern int sqlite3_shell(int, char**);
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  g.fNoThHook = 1;







<







 







|
|



<
<
<
<
<



|
|

|
|
<
<
<
<
<
<
<
<
<
<
<






|
>
|







146
147
148
149
150
151
152

153
154
155
156
157
158
159
...
253
254
255
256
257
258
259
260
261
262
263
264





265
266
267
268
269
270
271
272











273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  const void *notUsed
){
  add_content_sql_commands(db);
  db_add_aux_functions(db);
  re_add_sql_func(db);
  search_sql_setup(db);
  foci_register(db);

  g.repositoryOpen = 1;
  g.db = db;
  sqlite3_db_config(db, SQLITE_DBCONFIG_MAINDBNAME, "repository");
  db_maybe_set_encryption_key(db, g.zRepositoryName);
  if( g.zLocalDbName ){
    char *zSql = sqlite3_mprintf("ATTACH %Q AS 'localdb' KEY ''",
                                 g.zLocalDbName);
................................................................................
**
** WARNING:  Careless use of this command can corrupt a Fossil repository
** in ways that are unrecoverable.  Be sure you know what you are doing before
** running any SQL commands that modify the repository database.
**
** The following extensions to the usual SQLite commands are provided:
**
**    content(X)                Return the content of artifact X.  X can be an
**                              artifact hash or prefix or a tag.
**
**    compress(X)               Compress text X.
**





**    decompress(X)             Decompress text X.  Undoes the work of
**                              compress(X).
**
**    checkin_mtime(X,Y)        Return the mtime for the file Y (a BLOB.RID)
**                              found in check-in X (another BLOB.RID value).
**
**    symbolic_name_to_rid(X)   Return the BLOB.RID corresponding to symbolic
**                              name X.











**
**    now()                     Return the number of seconds since 1970.
**
**    REGEXP                    The REGEXP operator works, unlike in
**                              standard SQLite.
**
**    files_of_checkin(X)       A table-valued function that returns info on
**                              all files contained in check-in X.  Example:
**                                SELECT * FROM files_of_checkin('trunk');
*/
void cmd_sqlite3(void){
  int noRepository;
  const char *zConfigDb;
  extern int sqlite3_shell(int, char**);
#ifdef FOSSIL_ENABLE_TH1_HOOKS
  g.fNoThHook = 1;

Changes to src/sqlite3.c.

1
2
3
4
5
6
7
8
9
10
....
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
....
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
....
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
....
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
....
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
....
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
.....
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
.....
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
.....
14947
14948
14949
14950
14951
14952
14953

14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972

14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
14988
14989
14990
14991
14992
14993
14994
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
.....
15025
15026
15027
15028
15029
15030
15031
15032
15033
15034
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
.....
16335
16336
16337
16338
16339
16340
16341
16342
16343
16344
16345
16346
16347
16348
16349
.....
17999
18000
18001
18002
18003
18004
18005
18006
18007
18008
18009
18010
18011
18012
18013
.....
19185
19186
19187
19188
19189
19190
19191
19192
19193
19194
19195
19196
19197
19198
19199
.....
27132
27133
27134
27135
27136
27137
27138
27139
27140
27141
27142
27143
27144
27145
27146
27147
27148
.....
27328
27329
27330
27331
27332
27333
27334
27335
27336
27337
27338
27339
27340
27341
27342
.....
27358
27359
27360
27361
27362
27363
27364
27365
27366
27367
27368
27369
27370
27371
27372
.....
28078
28079
28080
28081
28082
28083
28084

28085
28086

28087
28088
28089
28090
28091
28092
28093
.....
28151
28152
28153
28154
28155
28156
28157
28158
28159
28160
28161
28162
28163
28164
28165
.....
32153
32154
32155
32156
32157
32158
32159

32160
32161
32162
32163
32164
32165
32166
32167
32168
32169
32170
32171
32172
32173
32174
32175
32176
32177
32178

32179
32180
32181
32182
32183
32184
32185
32186
32187
32188
32189
32190
32191
32192
32193
32194
32195
32196
32197
32198
32199
32200
32201
32202
32203
32204
32205
32206
32207
32208
32209
32210
32211
32212
32213
32214
32215
32216
.....
51317
51318
51319
51320
51321
51322
51323
51324
51325
51326
51327
51328
51329
51330
51331
51332
51333
.....
54269
54270
54271
54272
54273
54274
54275
54276
54277
54278
54279
54280
54281
54282
54283
54284
54285
54286
54287
54288
54289
54290
.....
57657
57658
57659
57660
57661
57662
57663
57664
57665
57666
57667
57668
57669
57670
57671
57672
57673
57674
57675
57676
.....
58190
58191
58192
58193
58194
58195
58196
58197
58198
58199
58200
58201
58202
58203
58204
.....
62366
62367
62368
62369
62370
62371
62372
62373
62374
62375
62376
62377
62378
62379
62380
.....
64508
64509
64510
64511
64512
64513
64514
64515
64516
64517
64518
64519
64520
64521
64522
64523
64524
64525
64526
64527
64528
64529
64530
64531
64532
64533
64534
64535
.....
64593
64594
64595
64596
64597
64598
64599
64600
64601
64602
64603
64604
64605
64606
64607
.....
64621
64622
64623
64624
64625
64626
64627
64628
64629
64630
64631
64632
64633
64634
64635
64636
64637
64638
64639
64640
64641
64642
64643
64644



64645
64646
64647
64648
64649
64650
64651
64652
64653
64654
64655
64656
64657
64658
64659
64660
64661
64662
64663
64664
64665
64666
64667

64668
64669
64670
64671
64672
64673
64674
64675
64676
64677
64678
64679
64680
64681
64682
64683
64684
64685
.....
64721
64722
64723
64724
64725
64726
64727
64728
64729
64730
64731
64732
64733
64734
64735
64736
64737
.....
64745
64746
64747
64748
64749
64750
64751
64752
64753
64754
64755
64756
64757
64758
64759
64760
64761
64762
64763
64764
64765
64766
64767
64768
.....
64773
64774
64775
64776
64777
64778
64779
64780
64781
64782
64783
64784
64785
64786
64787
.....
64935
64936
64937
64938
64939
64940
64941
64942
64943





64944
64945

64946
64947
64948

64949

64950
64951
64952
64953
64954
64955
64956
64957
64958
64959
64960
64961
64962
64963
64964
64965
64966













64967
64968
64969
64970
64971






















64972




















64973
64974
64975
64976
64977
64978
64979
.....
65013
65014
65015
65016
65017
65018
65019
65020
65021
65022
65023
65024
65025
65026
65027
65028
65029
65030
65031
65032
65033
65034
65035
65036
65037
65038
65039
65040
65041
65042
65043
65044
65045
65046
65047
65048
65049
65050
65051
65052
65053
65054
65055
65056
65057
65058
65059
65060
65061
65062
65063
65064
65065
65066
65067
65068
65069
65070
65071
65072
65073
65074
65075
65076
65077
65078
65079
65080
65081
65082
65083
65084
65085
65086
65087
65088
65089
65090
65091
65092
65093
65094
65095
65096
65097
65098
65099
65100
65101
65102
65103
65104
65105
65106
65107
65108
65109
65110
65111
65112
65113
65114
65115
65116
65117
65118
65119
65120
.....
65249
65250
65251
65252
65253
65254
65255
65256
65257
65258
65259
65260
65261
65262
65263
65264
65265
65266

65267
65268
65269
65270
65271
65272
65273
65274
65275
65276

65277
65278
65279
65280
65281
65282
65283
65284
65285
65286
65287
65288
65289
65290
.....
68639
68640
68641
68642
68643
68644
68645
68646
68647
68648
68649
68650
68651
68652
68653
.....
69688
69689
69690
69691
69692
69693
69694
69695
69696
69697
69698
69699
69700
69701
69702
.....
69759
69760
69761
69762
69763
69764
69765
69766
69767
69768
69769
69770
69771
69772
69773
.....
69817
69818
69819
69820
69821
69822
69823
69824
69825
69826
69827
69828
69829
69830
69831
.....
69904
69905
69906
69907
69908
69909
69910
69911
69912
69913
69914
69915
69916
69917
69918
69919
69920
69921
69922
69923
69924
.....
70239
70240
70241
70242
70243
70244
70245
70246
70247
70248
70249
70250
70251
70252
70253
70254
70255
.....
70317
70318
70319
70320
70321
70322
70323
70324
70325
70326
70327
70328
70329
70330
70331
70332
70333
70334
.....
70490
70491
70492
70493
70494
70495
70496
70497
70498
70499
70500
70501
70502
70503
70504
.....
70599
70600
70601
70602
70603
70604
70605
70606
70607
70608
70609
70610
70611
70612
70613
.....
70639
70640
70641
70642
70643
70644
70645
70646
70647
70648
70649
70650
70651
70652
70653
70654
70655
70656
70657
70658
70659
.....
70840
70841
70842
70843
70844
70845
70846
70847
70848
70849
70850
70851
70852
70853
70854
70855
70856
70857
70858
70859
70860
70861
70862
.....
71074
71075
71076
71077
71078
71079
71080

71081

71082
71083
71084
71085
71086
71087
71088
71089
71090
71091

71092
71093
71094
71095
71096
71097
71098
.....
71099
71100
71101
71102
71103
71104
71105
71106
71107
71108
71109
71110
71111
71112
71113
.....
71349
71350
71351
71352
71353
71354
71355
71356
71357
71358
71359
71360
71361
71362
71363
.....
71391
71392
71393
71394
71395
71396
71397
71398
71399
71400
71401
71402
71403
71404
71405
.....
71420
71421
71422
71423
71424
71425
71426
71427
71428
71429
71430
71431
71432
71433
71434
71435
71436
.....
71769
71770
71771
71772
71773
71774
71775
71776
71777
71778
71779
71780
71781
71782
71783
71784
71785
71786
.....
71923
71924
71925
71926
71927
71928
71929
71930
71931
71932
71933
71934
71935
71936
71937
.....
71994
71995
71996
71997
71998
71999
72000
72001
72002
72003
72004
72005
72006
72007
72008
72009
72010
72011
.....
72356
72357
72358
72359
72360
72361
72362
72363
72364
72365
72366
72367
72368
72369
72370
72371
72372
.....
72707
72708
72709
72710
72711
72712
72713
72714
72715
72716
72717
72718
72719
72720
72721
72722
72723
72724
.....
72892
72893
72894
72895
72896
72897
72898
72899
72900
72901
72902
72903
72904
72905
72906
72907
72908
72909
72910
.....
72969
72970
72971
72972
72973
72974
72975
72976
72977
72978
72979
72980
72981
72982
72983
.....
73029
73030
73031
73032
73033
73034
73035
73036
73037
73038
73039
73040
73041
73042
73043
73044
73045
73046
73047
73048
73049
73050
73051
73052
73053
73054
73055
.....
74506
74507
74508
74509
74510
74511
74512
74513

74514
74515
74516
74517
74518
74519
74520
.....
74525
74526
74527
74528
74529
74530
74531

74532
74533
74534
74535
74536
74537
74538
.....
75373
75374
75375
75376
75377
75378
75379

75380
75381
75382
75383
75384
75385
75386
75387
75388
75389
75390
75391
75392
75393
75394
75395
75396
75397
75398
75399
75400
75401
75402
75403
75404




75405
75406
75407
75408
75409
75410
75411
75412
75413
75414
75415
75416
75417
75418
75419
75420
75421
.....
76857
76858
76859
76860
76861
76862
76863
76864
76865
76866
76867
76868
76869
76870
76871
.....
82318
82319
82320
82321
82322
82323
82324
82325
82326
82327
82328
82329
82330
82331
82332
82333
82334
82335
.....
82342
82343
82344
82345
82346
82347
82348
82349
82350
82351
82352
82353
82354
82355
82356
82357
82358
82359
82360
82361
82362
82363
82364
.....
82367
82368
82369
82370
82371
82372
82373
82374

82375
82376
82377
82378

82379
82380
82381
82382
82383
82384
82385
.....
82390
82391
82392
82393
82394
82395
82396
82397

82398
82399
82400
82401

82402
82403
82404
82405
82406
82407
82408
82409
82410
82411
82412
82413

82414
82415
82416
82417

82418
82419
82420
82421
82422
82423
82424
82425
82426
82427

82428
82429
82430
82431

82432
82433
82434
82435
82436
82437
82438
82439
82440
82441

82442
82443
82444
82445

82446
82447
82448
82449
82450
82451
82452
.....
82806
82807
82808
82809
82810
82811
82812
82813
82814
82815
82816
82817
82818
82819
82820
82821
82822
82823
82824
82825
82826
82827
.....
84092
84093
84094
84095
84096
84097
84098
84099
84100
84101
84102
84103
84104
84105
84106
84107
84108
84109
84110
84111
84112
84113
84114
84115
84116
84117
84118
84119
84120









84121
84122
84123
84124
84125
84126
84127
.....
84289
84290
84291
84292
84293
84294
84295
84296
84297
84298
84299
84300
84301
84302
84303
84304
84305
84306
84307
.....
84572
84573
84574
84575
84576
84577
84578
84579
84580
84581
84582
84583
84584
84585
84586
84587
84588
84589
84590
84591

84592
84593
84594
84595
84596
84597
84598
.....
84838
84839
84840
84841
84842
84843
84844












84845
84846
84847
84848
84849
84850
84851
.....
86065
86066
86067
86068
86069
86070
86071
86072
86073
86074
86075
86076
86077
86078
86079

86080
86081
86082
86083
86084
86085
86086
86087
.....
88039
88040
88041
88042
88043
88044
88045






88046

88047
88048
88049
88050
88051
88052
88053
.....
88060
88061
88062
88063
88064
88065
88066

88067
88068
88069
88070
88071




88072
88073
88074
88075
88076
88077
88078
.....
89632
89633
89634
89635
89636
89637
89638
89639

89640
89641
89642
89643
89644
89645
89646
.....
91041
91042
91043
91044
91045
91046
91047
91048
91049
91050
91051
91052
91053
91054
91055
91056
91057
91058
91059
91060
91061
91062
91063
91064
.....
96231
96232
96233
96234
96235
96236
96237
96238
96239
96240
96241
96242
96243
96244
96245
96246
96247
96248
96249
96250
96251
96252
96253
96254
96255
96256
96257
96258
96259
96260
96261
96262
96263
96264
96265
96266
96267
96268
96269
96270
96271
96272
96273
96274
96275
96276
.....
96329
96330
96331
96332
96333
96334
96335


96336
96337

96338
96339








96340
96341
96342
96343
96344
96345
96346
.....
96544
96545
96546
96547
96548
96549
96550
96551
96552
96553
96554
96555
96556
96557
96558
96559
96560
96561
96562
96563
96564
96565
96566
96567
96568
96569
.....
99306
99307
99308
99309
99310
99311
99312



99313
99314
99315
99316
99317
99318
99319
99320
99321
99322
99323
99324
.....
99410
99411
99412
99413
99414
99415
99416






99417
99418
99419
99420
99421
99422
99423
99424
99425
99426
99427
99428
99429

99430
99431
99432
99433
99434
99435
99436
.....
99475
99476
99477
99478
99479
99480
99481

99482
99483
99484
99485
99486
99487

99488
99489
99490
99491
99492
99493
99494
99495
99496
99497
99498
99499
99500
99501
99502
99503
99504
99505
99506
99507
99508

99509
99510
99511
99512
99513
99514
99515
.....
99554
99555
99556
99557
99558
99559
99560

99561
99562

99563
99564
99565
99566
99567
99568
99569
99570
99571
99572
99573
99574



99575






99576
99577


99578
99579
99580
99581
99582
99583
99584
......
102367
102368
102369
102370
102371
102372
102373
102374
102375
102376
102377

102378
102379
102380
102381
102382
102383
102384
102385
102386
102387
102388
102389
......
102444
102445
102446
102447
102448
102449
102450

102451
102452
102453
102454
102455
102456
102457
......
102764
102765
102766
102767
102768
102769
102770
102771
102772
102773
102774
102775
102776
102777
102778
......
106019
106020
106021
106022
106023
106024
106025
106026
106027
106028
106029
106030
106031
106032
106033
106034
106035
......
106955
106956
106957
106958
106959
106960
106961
106962
106963
106964
106965
106966
106967
106968
106969
106970
106971
106972
106973
......
108520
108521
108522
108523
108524
108525
108526
108527
108528
108529
108530
108531
108532
108533
108534
......
108690
108691
108692
108693
108694
108695
108696
108697
108698
108699
108700
108701
108702
108703
108704
108705
108706
108707
108708
......
114646
114647
114648
114649
114650
114651
114652
114653
114654
114655
114656
114657
114658
114659
114660
114661
114662
114663
......
117972
117973
117974
117975
117976
117977
117978
117979
117980
117981
117982
117983
117984
117985
117986
117987
117988
......
118224
118225
118226
118227
118228
118229
118230
118231
118232
118233
118234
118235
118236
118237
118238
118239
118240
118241
118242
118243
118244
......
118655
118656
118657
118658
118659
118660
118661
118662
118663
118664
118665
118666
118667
118668
118669
......
118718
118719
118720
118721
118722
118723
118724
118725
118726
118727
118728
118729
118730
118731
118732
......
129761
129762
129763
129764
129765
129766
129767
129768
129769
129770
129771
129772
129773
129774
129775
......
136547
136548
136549
136550
136551
136552
136553

136554
136555
136556
136557
136558
136559
136560
......
137124
137125
137126
137127
137128
137129
137130
137131
137132
137133
137134
137135
137136
137137
137138
137139
137140
137141
137142
137143
137144
137145
137146
137147
137148
137149
137150
137151
137152
137153
137154
137155
137156
137157
137158
137159
137160
137161
137162
137163
137164
137165
......
137336
137337
137338
137339
137340
137341
137342
137343
137344
137345
137346
137347
137348
137349
137350
137351
137352
......
137761
137762
137763
137764
137765
137766
137767
137768
137769
137770
137771
137772
137773
137774
137775
137776
137777
137778
137779
137780
137781
137782
......
139765
139766
139767
139768
139769
139770
139771
139772
139773
139774
139775
139776
139777
139778
139779
139780
139781
139782
139783
139784
......
153178
153179
153180
153181
153182
153183
153184
153185
153186
153187
153188
153189
153190
153191
153192
......
153210
153211
153212
153213
153214
153215
153216
153217
153218
153219
153220
153221
153222
153223
153224
153225
......
153268
153269
153270
153271
153272
153273
153274
153275
153276
153277
153278
153279
153280
153281
153282
153283
......
153337
153338
153339
153340
153341
153342
153343
153344
153345
153346
153347
153348
153349
153350
153351
153352
......
161381
161382
161383
161384
161385
161386
161387
161388
161389
161390
161391
161392
161393
161394
161395
......
168521
168522
168523
168524
168525
168526
168527
168528
168529
168530
168531
168532
168533
168534
168535
168536
168537
......
170979
170980
170981
170982
170983
170984
170985
170986
170987
170988
170989
170990
170991
170992
170993
170994
170995
......
172868
172869
172870
172871
172872
172873
172874
172875
172876
172877
172878
172879
172880
172881
172882
172883
172884
172885
......
175776
175777
175778
175779
175780
175781
175782
175783
175784
175785
175786
175787
175788
175789
175790
......
176890
176891
176892
176893
176894
176895
176896
176897
176898
176899
176900
176901
176902
176903
176904
......
177000
177001
177002
177003
177004
177005
177006
177007
177008
177009
177010
177011
177012
177013
177014
......
188800
188801
188802
188803
188804
188805
188806
188807
188808
188809
188810
188811
188812
188813
188814
......
199860
199861
199862
199863
199864
199865
199866
199867
199868
199869
199870
199871
199872
199873
199874
......
199875
199876
199877
199878
199879
199880
199881
199882
199883
199884
199885
199886
199887
199888
199889
......
212210
212211
212212
212213
212214
212215
212216
212217
212218
212219
212220
212221
212222
212223
212224
212225
212226
212227
212228
212229
212230
212231
......
217254
217255
217256
217257
217258
217259
217260
217261
217262
217263
217264
217265
217266
217267
217268
......
222018
222019
222020
222021
222022
222023
222024
222025
222026
222027
222028
222029
222030
222031
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.28.0.  By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
................................................................................
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.28.0"
#define SQLITE_VERSION_NUMBER 3028000
#define SQLITE_SOURCE_ID      "2019-03-17 23:59:02 cc5ab96715ebb1089b4e9aa647badd2510aaa056f26004718f921f4ac07e2f93"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
................................................................................
** does not affect the value returned by sqlite3_total_changes().
** 
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers 
** are not counted.
**
** The [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D.  Any changes by other database connections are ignored.
** To detect changes against a database file from other database
** connections use the [PRAGMA data_version] command or the
** [SQLITE_FCNTL_DATA_VERSION] [file control].
** 
** If a separate thread makes changes on the same database connection
................................................................................
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
** prepared statement S is an EXPLAIN statement, or 2 if the
** statement S is an EXPLAIN QUERY PLAN.
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
** an ordinary statement or a NULL pointer.
*/
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite3_step(S)] but has neither run to completion (returned
................................................................................
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to the bind API fails,
** except the destructor is not called if the third parameter is a NULL
** pointer or the fourth parameter is negative.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
................................................................................
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** this function will return either a NULL pointer or an empty string.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function,
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
................................................................................
#define OP_OpenPseudo    116 /* synopsis: P3 columns in r[P2]              */
#define OP_Close         117
#define OP_ColumnsUsed   118
#define OP_SeekHit       119 /* synopsis: seekHit=P2                       */
#define OP_Sequence      120 /* synopsis: r[P2]=cursor[P1].ctr++           */
#define OP_NewRowid      121 /* synopsis: r[P2]=rowid                      */
#define OP_Insert        122 /* synopsis: intkey=r[P3] data=r[P2]          */

#define OP_Delete        123
#define OP_ResetCount    124
#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
#define OP_SorterData    126 /* synopsis: r[P2]=data                       */
#define OP_RowData       127 /* synopsis: r[P2]=data                       */
#define OP_Rowid         128 /* synopsis: r[P2]=rowid                      */
#define OP_NullRow       129
#define OP_SeekEnd       130
#define OP_SorterInsert  131 /* synopsis: key=r[P2]                        */
#define OP_IdxInsert     132 /* synopsis: key=r[P2]                        */
#define OP_IdxDelete     133 /* synopsis: key=r[P2@P3]                     */
#define OP_DeferredSeek  134 /* synopsis: Move P3 to P1.rowid if needed    */
#define OP_IdxRowid      135 /* synopsis: r[P2]=rowid                      */
#define OP_Destroy       136
#define OP_Clear         137
#define OP_ResetSorter   138
#define OP_CreateBtree   139 /* synopsis: r[P2]=root iDb=P1 flags=P3       */
#define OP_SqlExec       140
#define OP_Real          141 /* same as TK_FLOAT, synopsis: r[P2]=P4       */

#define OP_ParseSchema   142
#define OP_LoadAnalysis  143
#define OP_DropTable     144
#define OP_DropIndex     145
#define OP_DropTrigger   146
#define OP_IntegrityCk   147
#define OP_RowSetAdd     148 /* synopsis: rowset(P1)=r[P2]                 */
#define OP_Param         149
#define OP_FkCounter     150 /* synopsis: fkctr[P1]+=P2                    */
#define OP_MemMax        151 /* synopsis: r[P1]=max(r[P1],r[P2])           */
#define OP_OffsetLimit   152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
#define OP_AggInverse    153 /* synopsis: accum=r[P3] inverse(r[P2@P5])    */
#define OP_AggStep       154 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_AggStep1      155 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_AggValue      156 /* synopsis: r[P3]=value N=P2                 */
#define OP_AggFinal      157 /* synopsis: accum=r[P1] N=P2                 */
#define OP_Expire        158
#define OP_TableLock     159 /* synopsis: iDb=P1 root=P2 write=P3          */
#define OP_VBegin        160
#define OP_VCreate       161
#define OP_VDestroy      162
#define OP_VOpen         163
#define OP_VColumn       164 /* synopsis: r[P3]=vcolumn(P2)                */
#define OP_VRename       165
#define OP_Pagecount     166
#define OP_MaxPgcnt      167
#define OP_Trace         168
#define OP_CursorHint    169
#define OP_Noop          170
#define OP_Explain       171
#define OP_Abortable     172

/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */
#define OPFLG_IN1         0x02  /* in1:   P1 is an input */
................................................................................
/*  72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
/*  80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
/*  88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\
/*  96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00,\
/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00,}

/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode.  The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
................................................................................
#endif
  void *pCommitArg;                 /* Argument to xCommitCallback() */
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */
  void (*xRollbackCallback)(void*); /* Invoked at every commit. */
  void *pUpdateArg;
  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
  Parse *pParse;                /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  void *pPreUpdateArg;          /* First argument to xPreUpdateCallback */
  void (*xPreUpdateCallback)(   /* Registered using sqlite3_preupdate_hook() */
    void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
  );
  PreUpdate *pPreUpdate;        /* Context for active pre-update callback */
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
................................................................................
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nTableLock;        /* Number of locks in aTableLock */
  TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  Parse *pParentParse; /* Parent parser if this parser is nested */
  int addrCrTab;       /* Address of OP_CreateBtree opcode on CREATE TABLE */
  u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */
................................................................................
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
................................................................................
SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
  if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
    db->mallocFailed = 1;
    if( db->nVdbeExec>0 ){
      db->u1.isInterrupted = 1;
    }
    db->lookaside.bDisable++;
    if( db->pParse ){
      db->pParse->rc = SQLITE_NOMEM_BKPT;
    }
  }
}

/*
** This routine reactivates the memory allocator and clears the
** db->mallocFailed flag as necessary.
**
................................................................................

/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
  assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
  p->accError = eError;
  if( p->mxAlloc ) sqlite3_str_reset(p);
}

/*
** Extra argument values from a PrintfArguments object
*/
static sqlite3_int64 getIntArg(PrintfArguments *p){
  if( p->nArg<=p->nUsed ) return 0;
................................................................................
** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
** Do the size check before the memory allocation to prevent rogue
** SQL from requesting large allocations using the precision or width
** field of the printf() function.
*/
static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
  char *z;
  if( pAccum->accError ) return 0;
  if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
    setStrAccumError(pAccum, SQLITE_TOOBIG);
    return 0;
  }
  z = sqlite3DbMallocRaw(pAccum->db, n);
  if( z==0 ){
    setStrAccumError(pAccum, SQLITE_NOMEM);
................................................................................
  assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
  if( p->accError ){
    testcase(p->accError==SQLITE_TOOBIG);
    testcase(p->accError==SQLITE_NOMEM);
    return 0;
  }
  if( p->mxAlloc==0 ){

    setStrAccumError(p, SQLITE_TOOBIG);
    return p->nAlloc - p->nChar - 1;

  }else{
    char *zOld = isMalloced(p) ? p->zText : 0;
    i64 szNew = p->nChar;
    szNew += N + 1;
    if( szNew+p->nChar<=p->mxAlloc ){
      /* Force exponential buffer size growth as long as it does not overflow,
      ** to avoid having to call this routine too often */
................................................................................
** Append N bytes of text from z to the StrAccum object.  Increase the
** size of the memory allocation for StrAccum if necessary.
*/
SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
  assert( z!=0 || N==0 );
  assert( p->zText!=0 || p->nChar==0 || p->accError );
  assert( N>=0 );
  assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );
  if( p->nChar+N >= p->nAlloc ){
    enlargeAndAppend(p,z,N);
  }else if( N ){
    assert( p->zText );
    p->nChar += N;
    memcpy(&p->zText[p->nChar-N], z, N);
  }
................................................................................
    /* 116 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
    /* 117 */ "Close"            OpHelp(""),
    /* 118 */ "ColumnsUsed"      OpHelp(""),
    /* 119 */ "SeekHit"          OpHelp("seekHit=P2"),
    /* 120 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
    /* 121 */ "NewRowid"         OpHelp("r[P2]=rowid"),
    /* 122 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),

    /* 123 */ "Delete"           OpHelp(""),
    /* 124 */ "ResetCount"       OpHelp(""),
    /* 125 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
    /* 126 */ "SorterData"       OpHelp("r[P2]=data"),
    /* 127 */ "RowData"          OpHelp("r[P2]=data"),
    /* 128 */ "Rowid"            OpHelp("r[P2]=rowid"),
    /* 129 */ "NullRow"          OpHelp(""),
    /* 130 */ "SeekEnd"          OpHelp(""),
    /* 131 */ "SorterInsert"     OpHelp("key=r[P2]"),
    /* 132 */ "IdxInsert"        OpHelp("key=r[P2]"),
    /* 133 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
    /* 134 */ "DeferredSeek"     OpHelp("Move P3 to P1.rowid if needed"),
    /* 135 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
    /* 136 */ "Destroy"          OpHelp(""),
    /* 137 */ "Clear"            OpHelp(""),
    /* 138 */ "ResetSorter"      OpHelp(""),
    /* 139 */ "CreateBtree"      OpHelp("r[P2]=root iDb=P1 flags=P3"),
    /* 140 */ "SqlExec"          OpHelp(""),
    /* 141 */ "Real"             OpHelp("r[P2]=P4"),

    /* 142 */ "ParseSchema"      OpHelp(""),
    /* 143 */ "LoadAnalysis"     OpHelp(""),
    /* 144 */ "DropTable"        OpHelp(""),
    /* 145 */ "DropIndex"        OpHelp(""),
    /* 146 */ "DropTrigger"      OpHelp(""),
    /* 147 */ "IntegrityCk"      OpHelp(""),
    /* 148 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
    /* 149 */ "Param"            OpHelp(""),
    /* 150 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
    /* 151 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
    /* 152 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
    /* 153 */ "AggInverse"       OpHelp("accum=r[P3] inverse(r[P2@P5])"),
    /* 154 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
    /* 155 */ "AggStep1"         OpHelp("accum=r[P3] step(r[P2@P5])"),
    /* 156 */ "AggValue"         OpHelp("r[P3]=value N=P2"),
    /* 157 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
    /* 158 */ "Expire"           OpHelp(""),
    /* 159 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
    /* 160 */ "VBegin"           OpHelp(""),
    /* 161 */ "VCreate"          OpHelp(""),
    /* 162 */ "VDestroy"         OpHelp(""),
    /* 163 */ "VOpen"            OpHelp(""),
    /* 164 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
    /* 165 */ "VRename"          OpHelp(""),
    /* 166 */ "Pagecount"        OpHelp(""),
    /* 167 */ "MaxPgcnt"         OpHelp(""),
    /* 168 */ "Trace"            OpHelp(""),
    /* 169 */ "CursorHint"       OpHelp(""),
    /* 170 */ "Noop"             OpHelp(""),
    /* 171 */ "Explain"          OpHelp(""),
    /* 172 */ "Abortable"        OpHelp(""),
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
................................................................................
**   * the database file is open,
**   * there are no dirty pages in the cache, and
**   * the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
  if( pPager->fd->pMethods==0 ) return 0;
  if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
#ifdef SQLITE_HAS_CODEC
  if( pPager->xCodec!=0 ) return 0;
#endif
#ifndef SQLITE_OMIT_WAL
  if( pPager->pWal ){
    u32 iRead = 0;
    int rc;
    rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
    return (rc==SQLITE_OK && iRead==0);
  }
................................................................................
    char *pNew = NULL;             /* New temp space */
    i64 nByte = 0;

    if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
      rc = sqlite3OsFileSize(pPager->fd, &nByte);
    }
    if( rc==SQLITE_OK ){
      /* 8 bytes of zeroed overrun space is sufficient so that the b-tree
      * cell header parser will never run off the end of the allocation */
      pNew = (char *)sqlite3PageMalloc(pageSize+8);
      if( !pNew ){
        rc = SQLITE_NOMEM_BKPT;
      }else{
        memset(pNew+pageSize, 0, 8);
      }
    }

    if( rc==SQLITE_OK ){
      pager_reset(pPager);
      rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
    }
    if( rc==SQLITE_OK ){
................................................................................
  /* If the cache contains a page with page-number pgno, remove it
  ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 
  ** page pgno before the 'move' operation, it needs to be retained 
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = sqlite3PagerLookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
  if( pPgOld ){
    if( pPgOld->nRef>1 ){
      sqlite3PagerUnrefNotNull(pPgOld);
      return SQLITE_CORRUPT_BKPT;
    }
    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
    if( pPager->tempFile ){
      /* Do not discard pages from an in-memory database since we might
      ** need to rollback later.  Just move the page out of the way. */
      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
    }else{
      sqlite3PcacheDrop(pPgOld);
................................................................................

/*
** Release a lock obtained by an earlier successful call to
** sqlite3PagerSnapshotCheck().
*/
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){
  assert( pPager->pWal );
  sqlite3WalSnapshotUnlock(pPager->pWal);
}

#endif /* SQLITE_ENABLE_SNAPSHOT */
#endif /* !SQLITE_OMIT_WAL */

#ifdef SQLITE_ENABLE_ZIPVFS
/*
................................................................................
  u8 hdrOffset;        /* 100 for page 1.  0 otherwise */
  u8 childPtrSize;     /* 0 if leaf==1.  4 if leaf==0 */
  u8 max1bytePayload;  /* min(maxLocal,127) */
  u8 nOverflow;        /* Number of overflow cell bodies in aCell[] */
  u16 maxLocal;        /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
  u16 minLocal;        /* Copy of BtShared.minLocal or BtShared.minLeaf */
  u16 cellOffset;      /* Index in aData of first cell pointer */
  int nFree;           /* Number of free bytes on the page. -1 for unknown */
  u16 nCell;           /* Number of cells on this page, local and ovfl */
  u16 maskPage;        /* Mask for page offset */
  u16 aiOvfl[4];       /* Insert the i-th overflow cell before the aiOvfl-th
                       ** non-overflow cell */
  u8 *apOvfl[4];       /* Pointers to the body of overflow cells */
  BtShared *pBt;       /* Pointer to BtShared that this page is part of */
  u8 *aData;           /* Pointer to disk image of the page data */
................................................................................
  assert( pPage->nOverflow==0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  temp = 0;
  src = data = pPage->aData;
  hdr = pPage->hdrOffset;
  cellOffset = pPage->cellOffset;
  nCell = pPage->nCell;
  assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB );
  iCellFirst = cellOffset + 2*nCell;
  usableSize = pPage->pBt->usableSize;

  /* This block handles pages with two or fewer free blocks and nMaxFrag
  ** or fewer fragmented bytes. In this case it is faster to move the
  ** two (or one) blocks of cells using memmove() and add the required
  ** offsets to each pointer in the cell-pointer array than it is to 
  ** reconstruct the entire page.  */
  if( (int)data[hdr+7]<=nMaxFrag ){
    int iFree = get2byte(&data[hdr+1]);

    /* If the initial freeblock offset were out of bounds, that would have
    ** been detected by btreeComputeFreeSpace() when it was computing the
    ** number of free bytes on the page. */
    assert( iFree<=usableSize-4 );
    if( iFree ){
      int iFree2 = get2byte(&data[iFree]);
      if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
      if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
        u8 *pEnd = &data[cellOffset + nCell*2];
................................................................................
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:
  assert( pPage->nFree>=0 );
  if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( cbrk>=iCellFirst );
  put2byte(&data[hdr+5], cbrk);
  data[hdr+1] = 0;
  data[hdr+2] = 0;
................................................................................
** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned.
**
** Slots on the free list that are between 1 and 3 bytes larger than nByte
** will be ignored if adding the extra space to the fragmentation count
** causes the fragmentation count to exceed 60.
*/
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
  const int hdr = pPg->hdrOffset;            /* Offset to page header */
  u8 * const aData = pPg->aData;             /* Page data */
  int iAddr = hdr + 1;                       /* Address of ptr to pc */
  int pc = get2byte(&aData[iAddr]);          /* Address of a free slot */
  int x;                                     /* Excess size of the slot */
  int maxPC = pPg->pBt->usableSize - nByte;  /* Max address for a usable slot */
  int size;                                  /* Size of the free slot */

  assert( pc>0 );
  while( pc<=maxPC ){
    /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
    ** freeblock form a big-endian integer which is the size of the freeblock
    ** in bytes, including the 4-byte header. */
    size = get2byte(&aData[pc+2]);
    if( (x = size - nByte)>=0 ){
      testcase( x==4 );
      testcase( x==3 );



      if( x<4 ){
        /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
        ** number of bytes in fragments may not exceed 60. */
        if( aData[hdr+7]>57 ) return 0;

        /* Remove the slot from the free-list. Update the number of
        ** fragmented bytes within the page. */
        memcpy(&aData[iAddr], &aData[pc], 2);
        aData[hdr+7] += (u8)x;
      }else if( x+pc > maxPC ){
        /* This slot extends off the end of the usable part of the page */
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
        return 0;
      }else{
        /* The slot remains on the free-list. Reduce its size to account
        ** for the portion used by the new allocation. */
        put2byte(&aData[pc+2], x);
      }
      return &aData[pc + x];
    }
    iAddr = pc;
    pc = get2byte(&aData[pc]);
    if( pc<=iAddr+size ){

      if( pc ){
        /* The next slot in the chain is not past the end of the current slot */
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
      }
      return 0;
    }
  }
  if( pc>maxPC+nByte-4 ){
    /* The free slot chain extends off the end of the page */
    *pRc = SQLITE_CORRUPT_PAGE(pPg);
  }
  return 0;
}

/*
** Allocate nByte bytes of space from within the B-Tree page passed
** as the first argument. Write into *pIdx the index into pPage->aData[]
** of the first byte of allocated space. Return either SQLITE_OK or
................................................................................
    if( top==0 && pPage->pBt->usableSize==65536 ){
      top = 65536;
    }else{
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }

  /* If there is enough space between gap and top for one more cell pointer,
  ** and if the freelist is not empty, then search the
  ** freelist looking for a slot big enough to satisfy the request.
  */
  testcase( gap+2==top );
  testcase( gap+1==top );
  testcase( gap==top );
  if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
    u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
    if( pSpace ){
................................................................................

  /* The request could not be fulfilled using a freelist slot.  Check
  ** to see if defragmentation is necessary.
  */
  testcase( gap+2+nByte==top );
  if( gap+2+nByte>top ){
    assert( pPage->nCell>0 || CORRUPT_DB );
    assert( pPage->nFree>=0 );
    rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
    if( rc ) return rc;
    top = get2byteNotZero(&data[hdr+5]);
    assert( gap+2+nByte<=top );
  }


  /* Allocate memory from the gap in between the cell pointer array
  ** and the cell content area.  The btreeComputeFreeSpace() call has already
  ** validated the freelist.  Given that the freelist is valid, there
  ** is no way that the allocation can extend off the end of the page.
  ** The assert() below verifies the previous sentence.
  */
  top -= nByte;
  put2byte(&data[hdr+5], top);
  assert( top+nByte <= (int)pPage->pBt->usableSize );
................................................................................
/*
** Return a section of the pPage->aData to the freelist.
** The first byte of the new free block is pPage->aData[iStart]
** and the size of the block is iSize bytes.
**
** Adjacent freeblocks are coalesced.
**
** Even though the freeblock list was checked by btreeComputeFreeSpace(),
** that routine will not detect overlap between cells or freeblocks.  Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page.  So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
  u16 iPtr;                             /* Address of ptr to next freeblock */
................................................................................
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  pPage->max1bytePayload = pBt->max1bytePayload;
  return SQLITE_OK;
}

/*
** Compute the amount of freespace on the page.  In other words, fill
** in the pPage->nFree field.





*/
static int btreeComputeFreeSpace(MemPage *pPage){

  int pc;            /* Address of a freeblock within pPage->aData[] */
  u8 hdr;            /* Offset to beginning of page header */
  u8 *data;          /* Equal to pPage->aData */

  int usableSize;    /* Amount of usable space on each page */

  int nFree;         /* Number of unused bytes on the page */
  int top;           /* First byte of the cell content area */
  int iCellFirst;    /* First allowable cell or freeblock offset */
  int iCellLast;     /* Last possible cell or freeblock offset */

  assert( pPage->pBt!=0 );
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  assert( pPage->isInit==1 );
  assert( pPage->nFree<0 );

  usableSize = pPage->pBt->usableSize;
  hdr = pPage->hdrOffset;
  data = pPage->aData;













  /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
  ** the start of the cell content area. A zero value for this integer is
  ** interpreted as 65536. */
  top = get2byteNotZero(&data[hdr+5]);
  iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;






















  iCellLast = usableSize - 4;





















  /* Compute the total free space on the page
  ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
  ** start of the first freeblock on the page, or is zero if there are no
  ** freeblocks. */
  pc = get2byte(&data[hdr+1]);
  nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
................................................................................
  ** serves to verify that the offset to the start of the cell-content
  ** area, according to the page header, lies within the page.
  */
  if( nFree>usableSize ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  pPage->nFree = (u16)(nFree - iCellFirst);
  return SQLITE_OK;
}

/*
** Do additional sanity check after btreeInitPage() if
** PRAGMA cell_size_check=ON 
*/
static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){
  int iCellFirst;    /* First allowable cell or freeblock offset */
  int iCellLast;     /* Last possible cell or freeblock offset */
  int i;             /* Index into the cell pointer array */
  int sz;            /* Size of a cell */
  int pc;            /* Address of a freeblock within pPage->aData[] */
  u8 *data;          /* Equal to pPage->aData */
  int usableSize;    /* Maximum usable space on the page */
  int cellOffset;    /* Start of cell content area */

  iCellFirst = pPage->cellOffset + 2*pPage->nCell;
  usableSize = pPage->pBt->usableSize;
  iCellLast = usableSize - 4;
  data = pPage->aData;
  cellOffset = pPage->cellOffset;
  if( !pPage->leaf ) iCellLast--;
  for(i=0; i<pPage->nCell; i++){
    pc = get2byteAligned(&data[cellOffset+i*2]);
    testcase( pc==iCellFirst );
    testcase( pc==iCellLast );
    if( pc<iCellFirst || pc>iCellLast ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    sz = pPage->xCellSize(pPage, &data[pc]);
    testcase( pc+sz==usableSize );
    if( pc+sz>usableSize ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }
  return SQLITE_OK;
}

/*
** Initialize the auxiliary information for a disk block.
**
** Return SQLITE_OK on success.  If we see that the page does
** not contain a well-formed database page, then return 
** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed.  It only shows that
** we failed to detect any corruption.
*/
static int btreeInitPage(MemPage *pPage){
  u8 *data;          /* Equal to pPage->aData */
  BtShared *pBt;        /* The main btree structure */

  assert( pPage->pBt!=0 );
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  assert( pPage->isInit==0 );

  pBt = pPage->pBt;
  data = pPage->aData + pPage->hdrOffset;
  /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
  ** the b-tree page type. */
  if( decodeFlags(pPage, data[0]) ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  pPage->maskPage = (u16)(pBt->pageSize - 1);
  pPage->nOverflow = 0;
  pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
  pPage->aCellIdx = data + pPage->childPtrSize + 8;
  pPage->aDataEnd = pPage->aData + pBt->usableSize;
  pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  ** number of cells on the page. */
  pPage->nCell = get2byte(&data[3]);
  if( pPage->nCell>MX_CELL(pBt) ){
    /* To many cells for a single page.  The page must be corrupt */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  testcase( pPage->nCell==MX_CELL(pBt) );
  /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
  ** possible for a root page of a table that contains no rows) then the
  ** offset to the cell content area will equal the page size minus the
  ** bytes of reserved space. */
  assert( pPage->nCell>0
       || get2byteNotZero(&data[5])==pBt->usableSize
       || CORRUPT_DB );
  pPage->nFree = -1;  /* Indicate that this value is yet uncomputed */
  pPage->isInit = 1;
  if( pBt->db->flags & SQLITE_CellSizeCk ){
    return btreeCellSizeCheck(pPage);
  }
  return SQLITE_OK;
}

/*
** Set up a raw page so that it looks like a database page holding
** no entries.
*/
................................................................................
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pCur==0 || ppPage==&pCur->pPage );
  assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
  assert( pCur==0 || pCur->iPage>0 );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
    goto getAndInitPage_error1;
  }
  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
  if( rc ){
    goto getAndInitPage_error1;
  }
  *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  if( (*ppPage)->isInit==0 ){
    btreePageFromDbPage(pDbPage, pgno, pBt);
    rc = btreeInitPage(*ppPage);
    if( rc!=SQLITE_OK ){

      goto getAndInitPage_error2;
    }
  }
  assert( (*ppPage)->pgno==pgno );
  assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );

  /* If obtaining a child page for a cursor, we must verify that the page is
  ** compatible with the root page. */
  if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
    rc = SQLITE_CORRUPT_PGNO(pgno);

    goto getAndInitPage_error2;
  }
  return SQLITE_OK;

getAndInitPage_error2:
  releasePage(*ppPage);
getAndInitPage_error1:
  if( pCur ){
    pCur->iPage--;
    pCur->pPage = pCur->apPage[pCur->iPage];
  }
  testcase( pgno==0 );
  assert( pgno!=0 || rc==SQLITE_CORRUPT );
  return rc;
................................................................................
          pCur->ix = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
          pCur->curFlags &= ~BTCF_ValidOvfl;
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
          sqlite3_free(pCellKey);
        }
        assert( 
            (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
         && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
        );
        if( c<0 ){
................................................................................
  int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */

  if( *pRC ) return;
  assert( idx>=0 && idx<pPage->nCell );
  assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->nFree>=0 );
  data = pPage->aData;
  ptr = &pPage->aCellIdx[2*idx];
  pc = get2byte(ptr);
  hdr = pPage->hdrOffset;
  testcase( pc==get2byte(&data[hdr+5]) );
  testcase( pc+sz==pPage->pBt->usableSize );
  if( pc+sz > pPage->pBt->usableSize ){
................................................................................
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  /* The cell should normally be sized correctly.  However, when moving a
  ** malformed cell from a leaf page to an interior page, if the cell size
  ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
  ** might be less than 8 (leaf-size + pointer) on the interior node.  Hence
  ** the term after the || in the following assert(). */
  assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
  assert( pPage->nFree>=0 );
  if( pPage->nOverflow || sz+2>pPage->nFree ){
    if( pTemp ){
      memcpy(pTemp, pCell, sz);
      pCell = pTemp;
    }
    if( iChild ){
      put4byte(pCell, iChild);
................................................................................
    }
    pIns = pPage->aCellIdx + i*2;
    memmove(pIns+2, pIns, 2*(pPage->nCell - i));
    put2byte(pIns, idx);
    pPage->nCell++;
    /* increment the cell count */
    if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
    assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB );
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pPage->pBt->autoVacuum ){
      /* The cell may contain a pointer to an overflow page. If so, write
      ** the entry for the overflow page into the pointer map.
      */
      ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
    }
................................................................................
**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
**    ixNx[4] = Total number of cells.
**
** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
** are used and they point to the leaf pages only, and the ixNx value are:
**
**    ixNx[0] = Number of cells in Child-1.
**    ixNx[1] = Number of cells in Child-1 and Child-2.
**    ixNx[2] = Total number of cells.
**
** Sometimes when deleting, a child page can have zero cells.  In those
** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[]
** entries, shift down.  The end result is that each ixNx[] entry should
** be larger than the previous
*/
typedef struct CellArray CellArray;
struct CellArray {
  int nCell;              /* Number of cells in apCell[] */
  MemPage *pRef;          /* Reference page */
  u8 **apCell;            /* All cells begin balanced */
  u16 *szCell;            /* Local size of all cells in apCell[] */
................................................................................
  }

  /* Add any overflow cells */
  for(i=0; i<pPg->nOverflow; i++){
    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
    if( iCell>=0 && iCell<nNew ){
      pCellptr = &pPg->aCellIdx[iCell * 2];
      if( nCell>iCell ){
        memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
      }
      nCell++;
      if( pageInsertArray(
            pPg, pBegin, &pData, pCellptr,
            iCell+iNew, 1, pCArray
      ) ) goto editpage_fail;
    }
  }
................................................................................
  MemPage *pNew;                       /* Newly allocated page */
  int rc;                              /* Return Code */
  Pgno pgnoNew;                        /* Page number of pNew */

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  assert( pPage->nOverflow==1 );
  
  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;  /* dbfuzz001.test */
  assert( pPage->nFree>=0 );
  assert( pParent->nFree>=0 );

  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

................................................................................
    /* Reinitialize page pTo so that the contents of the MemPage structure
    ** match the new data. The initialization of pTo can actually fail under
    ** fairly obscure circumstances, even though it is a copy of initialized 
    ** page pFrom.
    */
    pTo->isInit = 0;
    rc = btreeInitPage(pTo);
    if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo);
    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
    }
  
    /* If this is an auto-vacuum database, update the pointer-map entries
    ** for any b-tree or overflow pages that pTo now contains the pointers to.
................................................................................
  */
  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
  assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );

  if( !aOvflSpace ){
    return SQLITE_NOMEM_BKPT;
  }
  assert( pParent->nFree>=0 );

  /* Find the sibling pages to balance. Also locate the cells in pParent 
  ** that divide the siblings. An attempt is made to find NN siblings on 
  ** either side of pPage. More siblings are taken from one side, however, 
  ** if there are fewer than NN siblings on the other side. If pParent
  ** has NB or fewer children then all children of pParent are taken.  
  **
................................................................................
  pgno = get4byte(pRight);
  while( 1 ){
    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }
    if( apOld[i]->nFree<0 ){
      rc = btreeComputeFreeSpace(apOld[i]);
      if( rc ){
        memset(apOld, 0, (i)*sizeof(MemPage*));
        goto balance_cleanup;
      }
    }
    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

    if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
      apDiv[i] = pParent->apOvfl[0];
      pgno = get4byte(apDiv[i]);
      szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
................................................................................
  ** 
  */
  usableSpace = pBt->usableSize - 12 + leafCorrection;
  for(i=k=0; i<nOld; i++, k++){
    MemPage *p = apOld[i];
    b.apEnd[k] = p->aDataEnd;
    b.ixNx[k] = cntOld[i];
    if( k && b.ixNx[k]==b.ixNx[k-1] ){
      k--;  /* Omit b.ixNx[] entry for child pages with no cells */
    }
    if( !leafData ){
      k++;
      b.apEnd[k] = pParent->aDataEnd;
      b.ixNx[k] = cntOld[i]+1;
    }
    assert( p->nFree>=0 );
    szNew[i] = usableSpace - p->nFree;
    for(j=0; j<p->nOverflow; j++){
      szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
    }
    cntNew[i] = cntOld[i];
  }
  k = nOld;
................................................................................
  ** associated with the right-child of each sibling may also need to be 
  ** updated. This happens below, after the sibling pages have been 
  ** populated, not here.
  */
  if( ISAUTOVACUUM ){
    MemPage *pOld;
    MemPage *pNew = pOld = apNew[0];

    int cntOldNext = pNew->nCell + pNew->nOverflow;

    int iNew = 0;
    int iOld = 0;

    for(i=0; i<b.nCell; i++){
      u8 *pCell = b.apCell[i];
      while( i==cntOldNext ){
        iOld++;
        assert( iOld<nNew || iOld<nOld );
        pOld = iOld<nNew ? apNew[iOld] : apOld[iOld];
        cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;

      }
      if( i==cntNew[iNew] ){
        pNew = apNew[++iNew];
        if( !leafData ) continue;
      }

      /* Cell pCell is destined for new sibling page pNew. Originally, it
................................................................................
      ** was either part of sibling page iOld (possibly an overflow cell), 
      ** or else the divider cell to the left of sibling page iOld. So,
      ** if sibling page iOld had the same page number as pNew, and if
      ** pCell really was a part of sibling page iOld (not a divider or
      ** overflow cell), we can skip updating the pointer map entries.  */
      if( iOld>=nNew
       || pNew->pgno!=aPgno[iOld]
       || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd)
      ){
        if( !leafCorrection ){
          ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
        }
        if( cachedCellSize(&b,i)>pNew->minLocal ){
          ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
        }
................................................................................
  if( rc ){
    *ppChild = 0;
    releasePage(pChild);
    return rc;
  }
  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  assert( pChild->nCell==pRoot->nCell || CORRUPT_DB );

  TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));

  /* Copy the overflow cells from pRoot to pChild */
  memcpy(pChild->aiOvfl, pRoot->aiOvfl,
         pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
  memcpy(pChild->apOvfl, pRoot->apOvfl,
................................................................................
  VVA_ONLY( int balance_quick_called = 0 );
  VVA_ONLY( int balance_deeper_called = 0 );

  do {
    int iPage = pCur->iPage;
    MemPage *pPage = pCur->pPage;

    if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
    if( iPage==0 ){
      if( pPage->nOverflow ){
        /* The root page of the b-tree is overfull. In this case call the
        ** balance_deeper() function to create a new child for the root-page
        ** and copy the current contents of the root-page to it. The
        ** next iteration of the do-loop will balance the child page.
        */ 
................................................................................
    }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
      break;
    }else{
      MemPage * const pParent = pCur->apPage[iPage-1];
      int const iIdx = pCur->aiIdx[iPage-1];

      rc = sqlite3PagerWrite(pParent->pDbPage);
      if( rc==SQLITE_OK && pParent->nFree<0 ){
        rc = btreeComputeFreeSpace(pParent);
      }
      if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
        if( pPage->intKeyLeaf
         && pPage->nOverflow==1
         && pPage->aiOvfl[0]==pPage->nCell
         && pParent->pgno!=1
         && pParent->nCell==iIdx
................................................................................

  }
  assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );

  pPage = pCur->pPage;
  assert( pPage->intKey || pX->nKey>=0 );
  assert( pPage->leaf || !pPage->intKey );
  if( pPage->nFree<0 ){
    rc = btreeComputeFreeSpace(pPage);
    if( rc ) return rc;
  }

  TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
          pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
          loc==0 ? "overwrite" : "new entry"));
  assert( pPage->isInit );
  newCell = pBt->pTmpSpace;
  assert( newCell!=0 );
................................................................................
  assert( pCur->eState==CURSOR_VALID );
  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );

  iCellDepth = pCur->iPage;
  iCellIdx = pCur->ix;
  pPage = pCur->pPage;
  pCell = findCell(pPage, iCellIdx);
  if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;

  /* If the bPreserve flag is set to true, then the cursor position must
  ** be preserved following this delete operation. If the current delete
  ** will cause a b-tree rebalance, then this is done by saving the cursor
  ** key and leaving the cursor in CURSOR_REQUIRESEEK state before 
  ** returning. 
  **
................................................................................
  ** node to replace the deleted cell.  */
  if( !pPage->leaf ){
    MemPage *pLeaf = pCur->pPage;
    int nCell;
    Pgno n;
    unsigned char *pTmp;

    if( pLeaf->nFree<0 ){
      rc = btreeComputeFreeSpace(pLeaf);
      if( rc ) return rc;
    }
    if( iCellDepth<pCur->iPage-1 ){
      n = pCur->apPage[iCellDepth+1]->pgno;
    }else{
      n = pCur->pPage->pgno;
    }
    pCell = findCell(pLeaf, pLeaf->nCell-1);
    if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
................................................................................
  int rc;
  MemPage *pPage = 0;
  BtShared *pBt = p->pBt;

  assert( sqlite3BtreeHoldsMutex(p) );
  assert( p->inTrans==TRANS_WRITE );
  assert( iTable>=2 );
  if( iTable>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;
  }

  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
    releasePage(pPage);
    return rc;
................................................................................
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
  IntegrityCk *pCheck,  /* Integrity checking context */
  int isFreeList,       /* True for a freelist.  False for overflow page list */
  int iPage,            /* Page number for first page in the list */
  u32 N                 /* Expected number of pages in the list */
){
  int i;
  u32 expected = N;
  int nErrAtStart = pCheck->nErr;
  while( iPage!=0 && pCheck->mxErr ){
    DbPage *pOvflPage;
    unsigned char *pOvflData;
    if( checkRef(pCheck, iPage) ) break;
    N--;
    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
................................................................................
  pPage->isInit = 0;
  if( (rc = btreeInitPage(pPage))!=0 ){
    assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
    checkAppendMsg(pCheck,
                   "btreeInitPage() returns error code %d", rc);
    goto end_of_check;
  }
  if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
    assert( rc==SQLITE_CORRUPT );
    checkAppendMsg(pCheck, "free space corruption", rc);
    goto end_of_check;
  }
  data = pPage->aData;
  hdr = pPage->hdrOffset;

  /* Set up for cell analysis */
  pCheck->zPfx = "On tree page %d cell %d: ";
  contentOffset = get2byteNotZero(&data[hdr+5]);
  assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
................................................................................
      }
      maxKey = info.nKey;
      keyCanBeEqual = 0;     /* Only the first key on the page may ==maxKey */
    }

    /* Check the content overflow list */
    if( info.nPayload>info.nLocal ){
      u32 nPage;       /* Number of pages on the overflow chain */
      Pgno pgnoOvfl;   /* First page of the overflow chain */
      assert( pc + info.nSize - 4 <= usableSize );
      nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
      pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
      if( pBt->autoVacuum ){
        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
................................................................................
    ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
    ** is the offset of the first freeblock, or zero if there are no
    ** freeblocks on the page. 
    */
    i = get2byte(&data[hdr+1]);
    while( i>0 ){
      int size, j;
      assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
      size = get2byte(&data[i+2]);
      assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
      btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
      /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
      ** big-endian integer which is the offset in the b-tree page of the next
      ** freeblock in the chain, or zero if the freeblock is the last on the
      ** chain. */
      j = get2byte(&data[i]);
      /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
      ** increasing offset. */
      assert( j==0 || j>i+size );     /* Enforced by btreeComputeFreeSpace() */
      assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
      i = j;
    }
    /* Analyze the min-heap looking for overlap between cells and/or 
    ** freeblocks, and counting the number of untracked bytes in nFrag.
    ** 
    ** Each min-heap entry is of the form:    (start_address<<16)|end_address.
    ** There is an implied first entry the covers the page header, the cell
................................................................................
  assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
  assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
  return rc;
#endif
}

/*
** Make sure pMem->z points to a writable allocation of at least n bytes.

**
** If the bPreserve argument is true, then copy of the content of
** pMem->z into the new allocation.  pMem must be either a string or
** blob if bPreserve is true.  If bPreserve is false, any prior content
** in pMem->z is discarded.
*/
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
................................................................................
  /* If the bPreserve flag is set to true, then the memory cell must already
  ** contain a valid string or blob value.  */
  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
  testcase( bPreserve && pMem->z==0 );

  assert( pMem->szMalloc==0
       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );

  if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
    pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    bPreserve = 0;
  }else{
    if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
    pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
  }
................................................................................
    iLimit = SQLITE_MAX_LENGTH;
  }
  flags = (enc==0?MEM_Blob:MEM_Str);
  if( nByte<0 ){
    assert( enc!=0 );
    if( enc==SQLITE_UTF8 ){
      nByte = 0x7fffffff & (int)strlen(z);

    }else{
      for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
    }
    flags |= MEM_Term;
  }

  /* The following block sets the new values of Mem.z and Mem.xDel. It
  ** also sets a flag in local variable "flags" to indicate the memory
  ** management (one of MEM_Dyn or MEM_Static).
  */
  if( xDel==SQLITE_TRANSIENT ){
    u32 nAlloc = nByte;
    if( flags&MEM_Term ){
      nAlloc += (enc==SQLITE_UTF8?1:2);
    }
    if( nByte>iLimit ){
      return SQLITE_TOOBIG;
    }
    testcase( nAlloc==0 );
    testcase( nAlloc==31 );
    testcase( nAlloc==32 );
    if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
      return SQLITE_NOMEM_BKPT;
    }
    memcpy(pMem->z, z, nAlloc);




  }else{
    sqlite3VdbeMemRelease(pMem);
    pMem->z = (char *)z;
    if( xDel==SQLITE_DYNAMIC ){
      pMem->zMalloc = pMem->z;
      pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
    }else{
      pMem->xDel = xDel;
      flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
    }
  }

  pMem->n = nByte;
  pMem->flags = flags;
  pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);

#ifndef SQLITE_OMIT_UTF16
................................................................................
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
     || opcode==OP_VDestroy
     || (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL)
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
    if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
................................................................................
**    3      The name of the table that the column derives from
**    4      The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
  sqlite3_stmt *pStmt,     /* The statement */
  int N,                   /* Which column to get the name for */
  int useUtf16,            /* True to return the name as UTF16 */
  int useType              /* What type of name */
){
  const void *ret;
  Vdbe *p;
  int n;
  sqlite3 *db;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pStmt==0 ){
................................................................................
  db = p->db;
  assert( db!=0 );
  n = sqlite3_column_count(pStmt);
  if( N<n && N>=0 ){
    N += useType*n;
    sqlite3_mutex_enter(db->mutex);
    assert( db->mallocFailed==0 );
#ifndef SQLITE_OMIT_UTF16
    if( useUtf16 ){
      ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
    }else
#endif
    {
      ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]);
    }
    /* A malloc may have failed inside of the _text() call. If this
    ** is the case, clear the mallocFailed flag and return NULL.
    */
    if( db->mallocFailed ){
      sqlite3OomClear(db);
      ret = 0;
    }
    sqlite3_mutex_leave(db->mutex);
................................................................................
}

/*
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 0, COLNAME_NAME);

}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 1, COLNAME_NAME);

}
#endif

/*
** Constraint:  If you have ENABLE_COLUMN_METADATA then you must
** not define OMIT_DECLTYPE.
*/
................................................................................

#ifndef SQLITE_OMIT_DECLTYPE
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 0, COLNAME_DECLTYPE);

}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 1, COLNAME_DECLTYPE);

}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_DECLTYPE */

#ifdef SQLITE_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 0, COLNAME_DATABASE);

}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 1, COLNAME_DATABASE);

}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 0, COLNAME_TABLE);

}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 1, COLNAME_TABLE);

}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 0, COLNAME_COLUMN);

}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
  return columnName(pStmt, N, 1, COLNAME_COLUMN);

}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_ENABLE_COLUMN_METADATA */


/******************************* sqlite3_bind_  ***************************
** 
................................................................................
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}

/*
** Return 1 if the statement is an EXPLAIN and return 2 if the
** statement is an EXPLAIN QUERY PLAN
*/
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->explain : 0;
}

/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
  Vdbe *v = (Vdbe*)pStmt;
  return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
}
................................................................................
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
    assert( 0 < db->nProgressOps );
    nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
  }else{
    nProgressLimit = 0xffffffff;
  }
#endif
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
  assert( p->bIsReader || p->readOnly!=0 );
  p->iCurrentTime = 0;
  assert( p->explain==0 );
  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
  sqlite3VdbeIOTraceSql(p);









#ifdef SQLITE_DEBUG
  sqlite3BeginBenignMalloc();
  if( p->pc==0
   && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
  ){
    int i;
    int once = 1;
................................................................................
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  /* Call the progress callback if it is configured and the required number
  ** of VDBE ops have been executed (either since this invocation of
  ** sqlite3VdbeExec() or since last time the progress callback was called).
  ** If the progress callback returns non-zero, exit the virtual machine with
  ** a return code SQLITE_ABORT.
  */
  while( nVmStep>=nProgressLimit && db->xProgress!=0 ){
    assert( db->nProgressOps!=0 );
    nProgressLimit += db->nProgressOps;
    if( db->xProgress(db->pProgressArg) ){
      nProgressLimit = 0xffffffff;
      rc = SQLITE_INTERRUPT;
      goto abort_due_to_error;
    }
  }
#endif
  
  break;
................................................................................
  pOp->opcode = OP_String;
  pOp->p1 = sqlite3Strlen30(pOp->p4.z);

#ifndef SQLITE_OMIT_UTF16
  if( encoding!=SQLITE_UTF8 ){
    rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
    assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );
    if( rc ) goto too_big;
    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
    assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
    assert( VdbeMemDynamic(pOut)==0 );
    pOut->szMalloc = 0;
    pOut->flags |= MEM_Static;
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite3DbFree(db, pOp->p4.z);
    }
    pOp->p4type = P4_DYNAMIC;
    pOp->p4.z = pOut->z;
    pOp->p1 = pOut->n;
  }

#endif
  if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }
  assert( rc==SQLITE_OK );
  /* Fall through to the next case, OP_String */
}
................................................................................
*/
case OP_ResultRow: {
  Mem *pMem;
  int i;
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 );
  assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );













  /* If this statement has violated immediate foreign key constraints, do
  ** not return the number of rows modified. And do not RELEASE the statement
  ** transaction. It needs to be rolled back.  */
  if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
    assert( db->flags&SQLITE_CountRows );
    assert( p->usesStmtJournal );
................................................................................
    op_column_read_header:
      i = pC->nHdrParsed;
      offset64 = aOffset[i];
      zHdr = zData + pC->iHdrOffset;
      zEndHdr = zData + aOffset[0];
      testcase( zHdr>=zEndHdr );
      do{
        if( (pC->aType[i] = t = zHdr[0])<0x80 ){
          zHdr++;
          offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
        }else{
          zHdr += sqlite3GetVarint32(zHdr, &t);
          pC->aType[i] = t;
          offset64 += sqlite3VdbeSerialTypeLen(t);
        }

        aOffset[++i] = (u32)(offset64 & 0xffffffff);
      }while( i<=p2 && zHdr<zEndHdr );

      /* The record is corrupt if any of the following are true:
      ** (1) the bytes of the header extend past the declared header size
      ** (2) the entire header was used but not all data was used
      ** (3) the end of the data extends beyond the end of the record.
      */
................................................................................
** and register P2 becomes ephemeral.  If the cursor is changed, the
** value of register P2 will then change.  Make sure this does not
** cause any problems.)
**
** This instruction only works on tables.  The equivalent instruction
** for indices is OP_IdxInsert.
*/






case OP_Insert: {

  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
  const char *zDb;  /* database name - used by the update hook */
  Table *pTab;      /* Table structure - used by update and pre-update hooks */
  BtreePayload x;   /* Payload to be inserted */
................................................................................
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->uc.pCursor!=0 );
  assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
  assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
  REGISTER_TRACE(pOp->p2, pData);
  sqlite3VdbeIncrWriteCounter(p, pC);


  pKey = &aMem[pOp->p3];
  assert( pKey->flags & MEM_Int );
  assert( memIsValid(pKey) );
  REGISTER_TRACE(pOp->p3, pKey);
  x.nKey = pKey->u.i;





  if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
    assert( pC->iDb>=0 );
    zDb = db->aDb[pC->iDb].zDbSName;
    pTab = pOp->p4.pTab;
    assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
  }else{
................................................................................
    for(i=0; i<p->nMem; i++){
      aMem[i].pScopyFrom = 0;  /* Prevent false-positive AboutToChange() errs */
      aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
    }
  }
#endif
  pOp = &aOp[-1];
  goto check_for_interrupt;

}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
................................................................................
    sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  while( nVmStep>=nProgressLimit && db->xProgress!=0 ){
    nProgressLimit += db->nProgressOps;
    if( db->xProgress(db->pProgressArg) ){
      nProgressLimit = 0xffffffff;
      rc = SQLITE_INTERRUPT;
      goto abort_due_to_error;
    }
  }
#endif
  p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
  sqlite3VdbeLeave(p);
  assert( rc!=SQLITE_OK || nExtraDelete==0 
       || sqlite3_strlike("DELETE%",p->zSql,0)!=0 
  );
  return rc;

................................................................................
      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
                   zType,0);
    }
  }
  return 0;
}

#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** Walker callback for resolveRemoveWindows().
*/
static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
  if( ExprHasProperty(pExpr, EP_WinFunc) ){
    Window **pp;
    for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
      if( *pp==pExpr->y.pWin ){
        *pp = (*pp)->pNextWin;
        break;
      }    
    }
  }
  return WRC_Continue;
}

/*
** Remove any Window objects owned by the expression pExpr from the
** Select.pWin list of Select object pSelect.
*/
static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){
  Walker sWalker;
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.xExprCallback = resolveRemoveWindowsCb;
  sWalker.u.pSelect = pSelect;
  sqlite3WalkExpr(&sWalker, pExpr);
}
#else
# define resolveRemoveWindows(x,y)
#endif

/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
** The Name context of the SELECT statement is pNC.  zType is either
** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
**
** This routine resolves each term of the clause into an expression.
** If the order-by term is an integer I between 1 and N (where N is the
................................................................................
    /* Otherwise, treat the ORDER BY term as an ordinary expression */
    pItem->u.x.iOrderByCol = 0;
    if( sqlite3ResolveExprNames(pNC, pE) ){
      return 1;
    }
    for(j=0; j<pSelect->pEList->nExpr; j++){
      if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){


        /* Since this expresion is being changed into a reference
        ** to an identical expression in the result set, remove all Window

        ** objects belonging to the expression from the Select.pWin list. */
        resolveRemoveWindows(pSelect, pE);








        pItem->u.x.iOrderByCol = j+1;
      }
    }
  }
  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
}

................................................................................
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }

#ifndef SQLITE_OMIT_WINDOWFUNC
    if( IN_RENAME_OBJECT ){
      Window *pWin;
      for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
        if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
         || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
        ){
          return WRC_Abort;
        }
      }
    }
#endif

    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }
................................................................................
    ** We will have to generate an ephemeral table to do the job.
    */
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( inFlags & IN_INDEX_LOOP ){
      pParse->nQueryLoop = 0;



    }else if( prRhsHasNull ){
      *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
    }
    assert( pX->op==TK_IN );
    sqlite3CodeRhsOfIN(pParse, pX, iTab);
    if( rMayHaveNull ){
      sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
    }
    pParse->nQueryLoop = savedNQueryLoop;
  }

  if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
................................................................................
**     x IN (SELECT a FROM b)     -- IN operator with subquery on the right
**
** The pExpr parameter is the IN operator.  The cursor number for the
** constructed ephermeral table is returned.  The first time the ephemeral
** table is computed, the cursor number is also stored in pExpr->iTable,
** however the cursor number returned might not be the same, as it might
** have been duplicated using OP_OpenDup.






**
** If the LHS expression ("x" in the examples) is a column value, or
** the SELECT statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN operator */
  int iTab                /* Use this cursor number */

){
  int addrOnce = 0;           /* Address of the OP_Once instruction at top */
  int addr;                   /* Address of OP_OpenEphemeral instruction */
  Expr *pLeft;                /* the LHS of the IN operator */
  KeyInfo *pKeyInfo = 0;      /* Key information */
  int nVal;                   /* Size of vector pLeft */
  Vdbe *v;                    /* The prepared statement under construction */
................................................................................

    addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  }

  /* Check to see if this is a vector IN operator */
  pLeft = pExpr->pLeft;
  nVal = sqlite3ExprVectorSize(pLeft);


  /* Construct the ephemeral table that will contain the content of
  ** RHS of the IN operator.
  */
  pExpr->iTable = iTab;
  addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);

#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
  }else{
    VdbeComment((v, "RHS of IN operator"));
  }
#endif
  pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);

  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    /* Case 1:     expr IN (SELECT ...)
    **
    ** Generate code to write the results of the select into the temporary
    ** table allocated and opened above.
    */
    Select *pSelect = pExpr->x.pSelect;
    ExprList *pEList = pSelect->pEList;

    ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
        addrOnce?"":"CORRELATED ", pSelect->selId
    ));

    /* If the LHS and RHS of the IN operator do not match, that
    ** error will have been caught long before we reach this point. */
    if( ALWAYS(pEList->nExpr==nVal) ){
      SelectDest dest;
      int i;
      sqlite3SelectDestInit(&dest, SRT_Set, iTab);
      dest.zAffSdst = exprINAffinity(pParse, pExpr);
................................................................................
      assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
      pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    }

    /* Loop through each expression in <exprlist>. */
    r1 = sqlite3GetTempReg(pParse);
    r2 = sqlite3GetTempReg(pParse);

    for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
      Expr *pE2 = pItem->pExpr;


      /* If the expression is not constant then we will need to
      ** disable the test that was generated above that makes sure
      ** this code only executes once.  Because for a non-constant
      ** expression we need to rerun this code each time.
      */
      if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
        sqlite3VdbeChangeToNoop(v, addrOnce);
        addrOnce = 0;
      }

      /* Evaluate the expression and insert it into the temp table */



      r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);






      sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);


    }
    sqlite3ReleaseTempReg(pParse, r1);
    sqlite3ReleaseTempReg(pParse, r2);
  }
  if( pKeyInfo ){
    sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
  }
................................................................................
    pVTab = sqlite3GetVTable(db, pTab);
    if( pVTab->pVtab->pModule->xRename==0 ){
      pVTab = 0;
    }
  }
#endif

  /* Begin a transaction for database iDb. Then modify the schema cookie
  ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(),
  ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the 
  ** nested SQL may raise an exception.  */

  v = sqlite3GetVdbe(pParse);
  if( v==0 ){
    goto exit_rename_table;
  }
  sqlite3MayAbort(pParse);

  /* figure out how many UTF-8 characters are in zName */
  zTabName = pTab->zName;
  nTabName = sqlite3Utf8CharLen(zTabName, -1);

  /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
  ** the schema to use the new table name.  */
................................................................................
  ** SQLite tables) that are identified by the name of the virtual table.
  */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( pVTab ){
    int i = ++pParse->nMem;
    sqlite3VdbeLoadString(v, i, zName);
    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);

  }
#endif

  renameReloadSchema(pParse, iDb);
  renameTestSchema(pParse, zDb, iDb==1);

exit_rename_table:
................................................................................
    goto exit_rename_column;
  }

  /* Do the rename operation using a recursive UPDATE statement that
  ** uses the sqlite_rename_column() SQL function to compute the new
  ** CREATE statement text for the sqlite_master table.
  */
  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
................................................................................
  ** remove the entry from the db->aDb[] array. i.e. put everything back the
  ** way we found it.
  */
  if( rc==SQLITE_OK ){
    sqlite3BtreeEnterAll(db);
    db->init.iDb = 0;
    db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
    if( !REOPEN_AS_MEMDB(db) ){
      rc = sqlite3Init(db, &zErrDyn);
    }
    sqlite3BtreeLeaveAll(db);
    assert( zErrDyn==0 || rc!=SQLITE_OK );
  }
#ifdef SQLITE_USER_AUTHENTICATION
  if( rc==SQLITE_OK ){
    u8 newAuth = 0;
    rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
................................................................................

  if( pParse->nErr ) return;
  assert( pParse->nested<10 );  /* Nesting should only be of limited depth */
  va_start(ap, zFormat);
  zSql = sqlite3VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    /* This can result either from an OOM or because the formatted string
    ** exceeds SQLITE_LIMIT_LENGTH.  In the latter case, we need to set
    ** an error */
    if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG;
    return;
  }
  pParse->nested++;
  memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
  memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
  sqlite3RunParser(pParse, zSql, &zErrMsg);
  sqlite3DbFree(db, zErrMsg);
  sqlite3DbFree(db, zSql);
................................................................................
    sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
                       SQLITE_IDXTYPE_PRIMARYKEY);
    if( db->mallocFailed || pParse->nErr ) return;
    pPk = sqlite3PrimaryKeyIndex(pTab);
    pTab->iPKey = -1;
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );

    /*
    ** Remove all redundant columns from the PRIMARY KEY.  For example, change
    ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)".  Later
    ** code assumes the PRIMARY KEY contains no repeated columns.
    */
    for(i=j=1; i<pPk->nKeyCol; i++){
................................................................................
      sqlite3ErrorMsg(pParse, "");
      return;
    }
    p->tnum = db->init.newTnum;
    if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
  }

  assert( (p->tabFlags & TF_HasPrimaryKey)==0
       || p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 );
  assert( (p->tabFlags & TF_HasPrimaryKey)!=0
       || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) );

  /* Special processing for WITHOUT ROWID Tables */
  if( tabOpts & TF_WithoutRowid ){
    if( (p->tabFlags & TF_Autoincrement) ){
      sqlite3ErrorMsg(pParse,
          "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
      return;
    }
................................................................................
*/
static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
  FuncDef *pDef;
  pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
  if( ALWAYS(pDef) ){
    pDef->funcFlags |= flagVal;
  }
  pDef = sqlite3FindFunction(db, zName, 3, SQLITE_UTF8, 0);
  if( pDef ){
    pDef->funcFlags |= flagVal;
  }
}

/*
** Register the built-in LIKE and GLOB functions.  The caseSensitive
** parameter determines whether or not the LIKE operator is case
** sensitive.  GLOB is always case sensitive.
*/
................................................................................
        sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
        VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
      }
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
    VdbeComment((v, "for %s", pIdx->zName));
#ifdef SQLITE_ENABLE_NULL_TRIM
    if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
      sqlite3SetMakeRecordP5(v, pIdx->pTable);
    }
#endif

    /* In an UPDATE operation, if this index is the PRIMARY KEY index 
    ** of a WITHOUT ROWID table and there has been no change the
    ** primary key, then no collision is possible.  The collision detection
    ** logic below can all be skipped. */
    if( isUpdate && pPk==pIdx && pkChng==0 ){
................................................................................
    pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
      assert( pParse->nested==0 );
      pik_flags |= OPFLAG_NCHANGE;
      pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
      if( update_flags==0 ){
        int r = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
        sqlite3VdbeAddOp4(v, OP_Insert, 
            iIdxCur+i, aRegIdx[i], r, (char*)pTab, P4_TABLE
        );
        sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
        sqlite3ReleaseTempReg(pParse, r);
      }
#endif
    }
    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
                         aRegIdx[i]+1,
                         pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
    sqlite3VdbeChangeP5(v, pik_flags);
................................................................................
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      sqlite3VdbeVerifyAbortable(v, onError);
      addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
      VdbeCoverage(v);
      sqlite3RowidConstraint(pParse, onError, pDest);
      sqlite3VdbeJumpHere(v, addr2);
      autoIncStep(pParse, regAutoinc, regRowid);
    }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_Vacuum) ){
      addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
    }else{
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      assert( (pDest->tabFlags & TF_Autoincrement)==0 );
    }
    sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
    if( db->mDbFlags & DBFLAG_Vacuum ){
................................................................................
        if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
      }
      if( i==pSrcIdx->nColumn ){
        idxInsFlags = OPFLAG_USESEEKRESULT;
        sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
      }
    }
    if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
      idxInsFlags |= OPFLAG_NCHANGE;
    }
    sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
    sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
................................................................................

/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
................................................................................
    if( pIn ){
      int iMap = 0;               /* Index in aiMap[] */
      pIn += i;
      for(i=iEq;i<pLoop->nLTerm; i++){
        if( pLoop->aLTerm[i]->pExpr==pX ){
          int iOut = iReg + i - iEq;
          if( eType==IN_INDEX_ROWID ){

            pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
          }else{
            int iCol = aiMap ? aiMap[iMap++] : 0;
            pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
          }
          sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
          if( i==iEq ){
................................................................................
    x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
    sqlite3WalkExpr(&w, pWInfo->pWhere);
    sqlite3WalkExprList(&w, pWInfo->pOrderBy);
    sqlite3WalkExprList(&w, pWInfo->pResultSet);
  }
}

/*
** The pTruth expression is always true because it is the WHERE clause
** a partial index that is driving a query loop.  Look through all of the
** WHERE clause terms on the query, and if any of those terms must be
** true because pTruth is true, then mark those WHERE clause terms as
** coded.
*/
static void whereApplyPartialIndexConstraints(
  Expr *pTruth,
  int iTabCur,
  WhereClause *pWC
){
  int i;
  WhereTerm *pTerm;
  while( pTruth->op==TK_AND ){
    whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC);
    pTruth = pTruth->pRight;
  }
  for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    Expr *pExpr;
    if( pTerm->wtFlags & TERM_CODED ) continue;
    pExpr = pTerm->pExpr;
    if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){
      pTerm->wtFlags |= TERM_CODED;
    }
  }
}

/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
  Parse *pParse,       /* Parsing context */
  Vdbe *v,             /* Prepared statement under construction */
................................................................................
    iReleaseReg = ++pParse->nMem;
    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
    if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
    VdbeCoverage(v);
    pLevel->op = OP_Noop;
    if( (pTerm->prereqAll & pLevel->notReady)==0 ){
      pTerm->wtFlags |= TERM_CODED;
    }
  }else if( (pLoop->wsFlags & WHERE_IPK)!=0
         && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
  ){
    /* Case 3:  We have an inequality comparison against the ROWID field.
    */
    int testOp = OP_Noop;
    int start;
................................................................................
    ** move forward to the next index.
    ** https://sqlite.org/src/info/4e8e4857d32d401f
    */
    if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
      whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
    }

    /* If a partial index is driving the loop, try to eliminate WHERE clause
    ** terms from the query that must be true due to the WHERE clause of
    ** the partial index
    */
    if( pIdx->pPartIdxWhere ){
      whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
    }

    /* Record the instruction used to terminate the loop. */
    if( pLoop->wsFlags & WHERE_ONEROW ){
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
................................................................................
    assert( p->x.pList==0 );
  }else if( ExprHasProperty(p, EP_xIsSelect) ){
    if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
    mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
  }else if( p->x.pList ){
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
  }
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( p->op==TK_FUNCTION && p->y.pWin ){
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
  }
#endif
  return mask;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
  return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
  int i;
................................................................................
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  sqlite3 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
  yyParser sEngine;    /* Space to hold the Lemon-generated Parser object */
#endif
  VVA_ONLY( u8 startedWithOom = db->mallocFailed );

  assert( zSql!=0 );
  mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
  }
  pParse->rc = SQLITE_OK;
................................................................................
    return SQLITE_NOMEM_BKPT;
  }
#endif
  assert( pParse->pNewTable==0 );
  assert( pParse->pNewTrigger==0 );
  assert( pParse->nVar==0 );
  assert( pParse->pVList==0 );
  pParse->pParentParse = db->pParse;
  db->pParse = pParse;
  while( 1 ){
    n = sqlite3GetToken((u8*)zSql, &tokenType);
    mxSqlLen -= n;
    if( mxSqlLen<0 ){
      pParse->rc = SQLITE_TOOBIG;
      break;
    }
................................................................................
      }
    }
    pParse->sLastToken.z = zSql;
    pParse->sLastToken.n = n;
    sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
    lastTokenParsed = tokenType;
    zSql += n;
    assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom );
    if( pParse->rc!=SQLITE_OK ) break;
  }
  assert( nErr==0 );
#ifdef YYTRACKMAXSTACKDEPTH
  sqlite3_mutex_enter(sqlite3MallocMutex());
  sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
      sqlite3ParserStackPeak(pEngine)
  );
................................................................................
    sqlite3DbFreeNN(db, p);
  }
  while( pParse->pZombieTab ){
    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite3DeleteTable(db, p);
  }
  db->pParse = pParse->pParentParse;
  pParse->pParentParse = 0;
  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
}


#ifdef SQLITE_ENABLE_NORMALIZE
/*
................................................................................
    if( !isFirstTerm ){
      zCsr += fts3GetVarint32(zCsr, &nPrefix);
    }
    isFirstTerm = 0;
    zCsr += fts3GetVarint32(zCsr, &nSuffix);
    
    assert( nPrefix>=0 && nSuffix>=0 );
    if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){
      rc = FTS_CORRUPT_VTAB;
      goto finish_scan;
    }
    if( (i64)nPrefix+nSuffix>nAlloc ){
      char *zNew;
      nAlloc = ((i64)nPrefix+nSuffix) * 2;
      zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
................................................................................
    if( !pPtr ){
      char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
      sqlite3_result_error(context, zErr, -1);
      sqlite3_free(zErr);
      return;
    }
  }
  if( fts3TokenizerEnabled(context) ){
    sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
  }
}

SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){
  static const char isFtsIdChar[] = {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
................................................................................
      return SQLITE_OK;
    }

    fts3SegReaderSetEof(pReader);

    /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
    ** blocks have already been traversed.  */
#ifdef CORRUPT_DB
    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB );
#endif
    if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
      return SQLITE_OK;
    }

    rc = sqlite3Fts3ReadBlock(
        p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, 
        (bIncr ? &pReader->nPopulate : 0)
................................................................................
    iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
    bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
  }
  if( rc!=SQLITE_OK ) goto finished;

  assert( csr.nSegment>0 );
  assert_fts3_nc( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
  assert_fts3_nc( 
    iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) 
  );

  memset(&filter, 0, sizeof(Fts3SegFilter));
  filter.flags = FTS3_SEGMENT_REQUIRE_POS;
  filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);

  rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
  while( SQLITE_OK==rc ){
................................................................................

  for(i=0; i<pIter->nPhrase; i++){
    SnippetPhrase *pPhrase = &pIter->aPhrase[i];
    if( pPhrase->pTail ){
      char *pCsr = pPhrase->pTail;
      int iCsr = pPhrase->iTail;

      while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
        int j;
        u64 mPhrase = (u64)1 << i;
        u64 mPos = (u64)1 << (iCsr - iStart);
        assert( iCsr>=iStart && (iCsr - iStart)<=64 );
        assert( i>=0 && i<=64 );
        if( (mCover|mCovered)&mPhrase ){
          iScore++;
................................................................................
  int rc;

  UNUSED_PARAMETER(iPhrase);
  rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
  nTerm = pExpr->pPhrase->nToken;
  if( pList ){
    fts3GetDeltaPosition(&pList, &iPos);
    assert_fts3_nc( iPos>=0 );
  }

  for(iTerm=0; iTerm<nTerm; iTerm++){
    TermOffset *pT = &p->aTerm[p->iTerm++];
    pT->iOff = nTerm-iTerm-1;
    pT->pList = pList;
    pT->iPos = iPos;
................................................................................
        }
      }

      if( !pTerm ){
        /* All offsets for this column have been gathered. */
        rc = SQLITE_DONE;
      }else{
        assert_fts3_nc( iCurrent<=iMinPos );
        if( 0==(0xFE&*pTerm->pList) ){
          pTerm->pList = 0;
        }else{
          fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
        }
        while( rc==SQLITE_OK && iCurrent<iMinPos ){
          rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
................................................................................

  aOut = sqlite3_malloc(nOut+1);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
    if( nOut2!=nOut ){
      sqlite3_free(aOut);
      sqlite3_result_error(context, "corrupt fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}

................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function,
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
................................................................................
            /* Set the szLeaf field */
            fts5PutU16(&buf.p[2], (u16)buf.n);
          }

          /* Set up the new page-index array */
          fts5BufferAppendVarint(&p->rc, &buf, 4);
          if( pSeg->iLeafPgno==pSeg->iTermLeafPgno 
           && pSeg->iEndofDoclist<pData->szLeaf
           && pSeg->iPgidxOff<=pData->nn
          ){
            int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
            fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
            fts5BufferAppendBlob(&p->rc, &buf, 
                pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
            );
          }

          pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
          fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
          fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
        }
        fts5DataRelease(pData);
................................................................................
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2019-03-15 16:17:32 0f2129f59f7df929106e2af876c2976dea6528c1dc1850d64cddb256f20e121a", -1, SQLITE_TRANSIENT);
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
................................................................................
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=222025
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2019-03-17 23:59:02 cc5ab96715ebb1089b4e9aa647badd2510aaa056f26004718f921f4ac07ealt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/


|







 







|
|
|







 







|
|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<







 







|
<
<







 







|







 







|







 







|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







|
|
|
|
|
|







 







<







 







<







 







|







 







<
<
<







 







|







 







<







 







>

<
>







 







|







 







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







<
<
<







 







<
<
|
<
|
<
<
<







 







|

<
<
<
<







 







|







 







|







 







|











|
|







 







<







 







|
|
|
|
|
|
|


|







>
>
>
|








<
<
<
<


|






|
>
|
<
|
|
<
|
<
<
<
<
<







 







|
|
|







 







<








|







 







|







 







|
|
>
>
>
>
>

<
>



>

>











|
<

|


>
>
>
>
>
>
>
>
>
>
>
>
>




<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<







 







|



|






>
|









>
|



|
<
<







 







|







 







<







 







<







 







|







 







|
|
<
<
<
<
<







 







|
|
<







 







|

<
<







 







<







 







<







 







<
<
<
<
<
<
<







 







<
<
<





<







 







>

>





|
<
<
|

>







 







|







 







|







 







<







 







<
<
<







 







<
<
<
<







 







<







 







<
<
<
<







 







<
<
<







 







|


|







 







<
<
<
<
<







 







|







 







|

|








|
|







 







|
>







 







>







 







>











|









|



>
>
>
>



<
<
<
<
|
|
<







 







<







 







|
|
|
|







 







<
<
<
<
<
<
|
<
|







 







|
>



|
>







 







|
>



|
>











|
>



|
>









|
>



|
>









|
>



|
>







 







<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<













>
>
>
>
>
>
>
>
>







 







|

|

<







 







<












>







 







>
>
>
>
>
>
>
>
>
>
>
>







 







|




<


>
|







 







>
>
>
>
>
>
|
>







 







>
|
|
|
|
|
>
>
>
>







 







|
>







 







|
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
|
<
>
|
<
>
>
>
>
>
>
>
>







 







<










<







 







>
>
>




|







 







>
>
>
>
>
>












|
>







 







>





|
>







|













>







 







>


>












>
>
>
|
>
>
>
>
>
>
|
|
>
>







 







|
|
|
|
>




<







 







>







 







<







 







<
|
<







 







|
<
<
<
<







 







<







 







<
<
<
<
<







 







<
<
<
<







 







<
|
<







 







<
<
|
|


<







 







|







 







|







 







|







 







>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<







 







<
<
<
<
<
<
<
<







 







<
<
<
<
<
<







 







<







 







<
<







 







<
|







 







<
<







 







|







 







<
|
<







 







<
|
<







 







|
<
|
<







 







|







 







|







 







|







 







<







 







|







 







|







 







|
<
|




|







 







|







 







|

|




1
2
3
4
5
6
7
8
9
10
....
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
....
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
....
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
....
4929
4930
4931
4932
4933
4934
4935












4936
4937
4938
4939
4940
4941
4942
....
5068
5069
5070
5071
5072
5073
5074
5075


5076
5077
5078
5079
5080
5081
5082
....
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
.....
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
.....
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
.....
14933
14934
14935
14936
14937
14938
14939
14940
14941
14942
14943
14944
14945
14946
14947
14948
14949
14950
14951
14952
14953
14954
14955
14956
14957

14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14972
14973
14974
14975
14976
14977
14978
14979
14980
14981
14982
14983
14984
14985
14986
14987
14988
14989
14990
14991
14992
14993
14994
14995
14996
14997
.....
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
.....
16322
16323
16324
16325
16326
16327
16328

16329
16330
16331
16332
16333
16334
16335
.....
17985
17986
17987
17988
17989
17990
17991

17992
17993
17994
17995
17996
17997
17998
.....
19170
19171
19172
19173
19174
19175
19176
19177
19178
19179
19180
19181
19182
19183
19184
.....
27117
27118
27119
27120
27121
27122
27123



27124
27125
27126
27127
27128
27129
27130
.....
27310
27311
27312
27313
27314
27315
27316
27317
27318
27319
27320
27321
27322
27323
27324
.....
27340
27341
27342
27343
27344
27345
27346

27347
27348
27349
27350
27351
27352
27353
.....
28059
28060
28061
28062
28063
28064
28065
28066
28067

28068
28069
28070
28071
28072
28073
28074
28075
.....
28133
28134
28135
28136
28137
28138
28139
28140
28141
28142
28143
28144
28145
28146
28147
.....
32135
32136
32137
32138
32139
32140
32141
32142
32143
32144
32145
32146
32147
32148
32149
32150
32151
32152
32153
32154
32155
32156
32157
32158
32159

32160
32161
32162
32163
32164
32165
32166
32167
32168
32169
32170
32171
32172
32173
32174
32175
32176
32177
32178
32179
32180
32181
32182
32183
32184
32185
32186
32187
32188
32189
32190
32191
32192
32193
32194
32195
32196
32197
32198
32199
.....
51300
51301
51302
51303
51304
51305
51306



51307
51308
51309
51310
51311
51312
51313
.....
54249
54250
54251
54252
54253
54254
54255


54256

54257



54258
54259
54260
54261
54262
54263
54264
.....
57631
57632
57633
57634
57635
57636
57637
57638
57639




57640
57641
57642
57643
57644
57645
57646
.....
58160
58161
58162
58163
58164
58165
58166
58167
58168
58169
58170
58171
58172
58173
58174
.....
62336
62337
62338
62339
62340
62341
62342
62343
62344
62345
62346
62347
62348
62349
62350
.....
64478
64479
64480
64481
64482
64483
64484
64485
64486
64487
64488
64489
64490
64491
64492
64493
64494
64495
64496
64497
64498
64499
64500
64501
64502
64503
64504
64505
.....
64563
64564
64565
64566
64567
64568
64569

64570
64571
64572
64573
64574
64575
64576
.....
64590
64591
64592
64593
64594
64595
64596
64597
64598
64599
64600
64601
64602
64603
64604
64605
64606
64607
64608
64609
64610
64611
64612
64613
64614
64615
64616
64617
64618
64619
64620
64621
64622
64623
64624
64625




64626
64627
64628
64629
64630
64631
64632
64633
64634
64635
64636
64637

64638
64639

64640





64641
64642
64643
64644
64645
64646
64647
.....
64683
64684
64685
64686
64687
64688
64689
64690
64691
64692
64693
64694
64695
64696
64697
64698
64699
.....
64707
64708
64709
64710
64711
64712
64713

64714
64715
64716
64717
64718
64719
64720
64721
64722
64723
64724
64725
64726
64727
64728
64729
.....
64734
64735
64736
64737
64738
64739
64740
64741
64742
64743
64744
64745
64746
64747
64748
.....
64896
64897
64898
64899
64900
64901
64902
64903
64904
64905
64906
64907
64908
64909
64910

64911
64912
64913
64914
64915
64916
64917
64918
64919
64920
64921
64922
64923
64924
64925
64926
64927
64928
64929

64930
64931
64932
64933
64934
64935
64936
64937
64938
64939
64940
64941
64942
64943
64944
64945
64946
64947
64948
64949
64950

64951
64952
64953
64954
64955
64956
64957
64958
64959
64960
64961
64962
64963
64964
64965
64966
64967
64968
64969
64970
64971
64972
64973
64974
64975
64976
64977
64978
64979
64980
64981
64982
64983
64984
64985
64986
64987
64988
64989
64990
64991
64992
64993
64994
64995
64996
64997
64998
64999
65000
.....
65034
65035
65036
65037
65038
65039
65040


























































































65041



65042
65043
65044
65045
65046
65047
65048
.....
65177
65178
65179
65180
65181
65182
65183
65184
65185
65186
65187
65188
65189
65190
65191
65192
65193
65194
65195
65196
65197
65198
65199
65200
65201
65202
65203
65204
65205
65206
65207
65208
65209
65210
65211


65212
65213
65214
65215
65216
65217
65218
.....
68567
68568
68569
68570
68571
68572
68573
68574
68575
68576
68577
68578
68579
68580
68581
.....
69616
69617
69618
69619
69620
69621
69622

69623
69624
69625
69626
69627
69628
69629
.....
69686
69687
69688
69689
69690
69691
69692

69693
69694
69695
69696
69697
69698
69699
.....
69743
69744
69745
69746
69747
69748
69749
69750
69751
69752
69753
69754
69755
69756
69757
.....
69830
69831
69832
69833
69834
69835
69836
69837
69838





69839
69840
69841
69842
69843
69844
69845
.....
70160
70161
70162
70163
70164
70165
70166
70167
70168

70169
70170
70171
70172
70173
70174
70175
.....
70237
70238
70239
70240
70241
70242
70243
70244
70245


70246
70247
70248
70249
70250
70251
70252
.....
70408
70409
70410
70411
70412
70413
70414

70415
70416
70417
70418
70419
70420
70421
.....
70516
70517
70518
70519
70520
70521
70522

70523
70524
70525
70526
70527
70528
70529
.....
70555
70556
70557
70558
70559
70560
70561







70562
70563
70564
70565
70566
70567
70568
.....
70749
70750
70751
70752
70753
70754
70755



70756
70757
70758
70759
70760

70761
70762
70763
70764
70765
70766
70767
.....
70979
70980
70981
70982
70983
70984
70985
70986
70987
70988
70989
70990
70991
70992
70993
70994


70995
70996
70997
70998
70999
71000
71001
71002
71003
71004
.....
71005
71006
71007
71008
71009
71010
71011
71012
71013
71014
71015
71016
71017
71018
71019
.....
71255
71256
71257
71258
71259
71260
71261
71262
71263
71264
71265
71266
71267
71268
71269
.....
71297
71298
71299
71300
71301
71302
71303

71304
71305
71306
71307
71308
71309
71310
.....
71325
71326
71327
71328
71329
71330
71331



71332
71333
71334
71335
71336
71337
71338
.....
71671
71672
71673
71674
71675
71676
71677




71678
71679
71680
71681
71682
71683
71684
.....
71821
71822
71823
71824
71825
71826
71827

71828
71829
71830
71831
71832
71833
71834
.....
71891
71892
71893
71894
71895
71896
71897




71898
71899
71900
71901
71902
71903
71904
.....
72249
72250
72251
72252
72253
72254
72255



72256
72257
72258
72259
72260
72261
72262
.....
72597
72598
72599
72600
72601
72602
72603
72604
72605
72606
72607
72608
72609
72610
72611
72612
72613
72614
.....
72782
72783
72784
72785
72786
72787
72788





72789
72790
72791
72792
72793
72794
72795
.....
72854
72855
72856
72857
72858
72859
72860
72861
72862
72863
72864
72865
72866
72867
72868
.....
72914
72915
72916
72917
72918
72919
72920
72921
72922
72923
72924
72925
72926
72927
72928
72929
72930
72931
72932
72933
72934
72935
72936
72937
72938
72939
72940
.....
74391
74392
74393
74394
74395
74396
74397
74398
74399
74400
74401
74402
74403
74404
74405
74406
.....
74411
74412
74413
74414
74415
74416
74417
74418
74419
74420
74421
74422
74423
74424
74425
.....
75260
75261
75262
75263
75264
75265
75266
75267
75268
75269
75270
75271
75272
75273
75274
75275
75276
75277
75278
75279
75280
75281
75282
75283
75284
75285
75286
75287
75288
75289
75290
75291
75292
75293
75294
75295
75296
75297
75298
75299




75300
75301

75302
75303
75304
75305
75306
75307
75308
.....
76744
76745
76746
76747
76748
76749
76750

76751
76752
76753
76754
76755
76756
76757
.....
82204
82205
82206
82207
82208
82209
82210
82211
82212
82213
82214
82215
82216
82217
82218
82219
82220
82221
.....
82228
82229
82230
82231
82232
82233
82234






82235

82236
82237
82238
82239
82240
82241
82242
82243
.....
82246
82247
82248
82249
82250
82251
82252
82253
82254
82255
82256
82257
82258
82259
82260
82261
82262
82263
82264
82265
82266
.....
82271
82272
82273
82274
82275
82276
82277
82278
82279
82280
82281
82282
82283
82284
82285
82286
82287
82288
82289
82290
82291
82292
82293
82294
82295
82296
82297
82298
82299
82300
82301
82302
82303
82304
82305
82306
82307
82308
82309
82310
82311
82312
82313
82314
82315
82316
82317
82318
82319
82320
82321
82322
82323
82324
82325
82326
82327
82328
82329
82330
82331
82332
82333
82334
82335
82336
82337
82338
82339
82340
82341
.....
82695
82696
82697
82698
82699
82700
82701








82702
82703
82704
82705
82706
82707
82708
.....
83973
83974
83975
83976
83977
83978
83979









83980
83981
83982
83983
83984
83985
83986
83987
83988
83989
83990
83991
83992
83993
83994
83995
83996
83997
83998
83999
84000
84001
84002
84003
84004
84005
84006
84007
84008
.....
84170
84171
84172
84173
84174
84175
84176
84177
84178
84179
84180

84181
84182
84183
84184
84185
84186
84187
.....
84452
84453
84454
84455
84456
84457
84458

84459
84460
84461
84462
84463
84464
84465
84466
84467
84468
84469
84470
84471
84472
84473
84474
84475
84476
84477
84478
.....
84718
84719
84720
84721
84722
84723
84724
84725
84726
84727
84728
84729
84730
84731
84732
84733
84734
84735
84736
84737
84738
84739
84740
84741
84742
84743
.....
85957
85958
85959
85960
85961
85962
85963
85964
85965
85966
85967
85968

85969
85970
85971
85972
85973
85974
85975
85976
85977
85978
85979
.....
87931
87932
87933
87934
87935
87936
87937
87938
87939
87940
87941
87942
87943
87944
87945
87946
87947
87948
87949
87950
87951
87952
.....
87959
87960
87961
87962
87963
87964
87965
87966
87967
87968
87969
87970
87971
87972
87973
87974
87975
87976
87977
87978
87979
87980
87981
87982
.....
89536
89537
89538
89539
89540
89541
89542
89543
89544
89545
89546
89547
89548
89549
89550
89551
.....
90946
90947
90948
90949
90950
90951
90952
90953









90954
90955
90956
90957
90958
90959
90960
.....
96127
96128
96129
96130
96131
96132
96133
































96134
96135
96136
96137
96138
96139
96140
.....
96193
96194
96195
96196
96197
96198
96199
96200
96201
96202

96203
96204

96205
96206
96207
96208
96209
96210
96211
96212
96213
96214
96215
96216
96217
96218
96219
.....
96417
96418
96419
96420
96421
96422
96423

96424
96425
96426
96427
96428
96429
96430
96431
96432
96433

96434
96435
96436
96437
96438
96439
96440
.....
99177
99178
99179
99180
99181
99182
99183
99184
99185
99186
99187
99188
99189
99190
99191
99192
99193
99194
99195
99196
99197
99198
.....
99284
99285
99286
99287
99288
99289
99290
99291
99292
99293
99294
99295
99296
99297
99298
99299
99300
99301
99302
99303
99304
99305
99306
99307
99308
99309
99310
99311
99312
99313
99314
99315
99316
99317
.....
99356
99357
99358
99359
99360
99361
99362
99363
99364
99365
99366
99367
99368
99369
99370
99371
99372
99373
99374
99375
99376
99377
99378
99379
99380
99381
99382
99383
99384
99385
99386
99387
99388
99389
99390
99391
99392
99393
99394
99395
99396
99397
99398
99399
.....
99438
99439
99440
99441
99442
99443
99444
99445
99446
99447
99448
99449
99450
99451
99452
99453
99454
99455
99456
99457
99458
99459
99460
99461
99462
99463
99464
99465
99466
99467
99468
99469
99470
99471
99472
99473
99474
99475
99476
99477
99478
99479
99480
99481
......
102264
102265
102266
102267
102268
102269
102270
102271
102272
102273
102274
102275
102276
102277
102278
102279

102280
102281
102282
102283
102284
102285
102286
......
102341
102342
102343
102344
102345
102346
102347
102348
102349
102350
102351
102352
102353
102354
102355
......
102662
102663
102664
102665
102666
102667
102668

102669
102670
102671
102672
102673
102674
102675
......
105916
105917
105918
105919
105920
105921
105922

105923

105924
105925
105926
105927
105928
105929
105930
......
106850
106851
106852
106853
106854
106855
106856
106857




106858
106859
106860
106861
106862
106863
106864
......
108411
108412
108413
108414
108415
108416
108417

108418
108419
108420
108421
108422
108423
108424
......
108580
108581
108582
108583
108584
108585
108586





108587
108588
108589
108590
108591
108592
108593
......
114531
114532
114533
114534
114535
114536
114537




114538
114539
114540
114541
114542
114543
114544
......
117853
117854
117855
117856
117857
117858
117859

117860

117861
117862
117863
117864
117865
117866
117867
......
118103
118104
118105
118106
118107
118108
118109


118110
118111
118112
118113

118114
118115
118116
118117
118118
118119
118120
......
118531
118532
118533
118534
118535
118536
118537
118538
118539
118540
118541
118542
118543
118544
118545
......
118594
118595
118596
118597
118598
118599
118600
118601
118602
118603
118604
118605
118606
118607
118608
......
129637
129638
129639
129640
129641
129642
129643
129644
129645
129646
129647
129648
129649
129650
129651
......
136423
136424
136425
136426
136427
136428
136429
136430
136431
136432
136433
136434
136435
136436
136437
......
137001
137002
137003
137004
137005
137006
137007




























137008
137009
137010
137011
137012
137013
137014
......
137185
137186
137187
137188
137189
137190
137191



137192
137193
137194
137195
137196
137197
137198
......
137607
137608
137609
137610
137611
137612
137613








137614
137615
137616
137617
137618
137619
137620
......
139603
139604
139605
139606
139607
139608
139609






139610
139611
139612
139613
139614
139615
139616
......
153010
153011
153012
153013
153014
153015
153016

153017
153018
153019
153020
153021
153022
153023
......
153041
153042
153043
153044
153045
153046
153047


153048
153049
153050
153051
153052
153053
153054
......
153097
153098
153099
153100
153101
153102
153103

153104
153105
153106
153107
153108
153109
153110
153111
......
153165
153166
153167
153168
153169
153170
153171


153172
153173
153174
153175
153176
153177
153178
......
161207
161208
161209
161210
161211
161212
161213
161214
161215
161216
161217
161218
161219
161220
161221
......
168347
168348
168349
168350
168351
168352
168353

168354

168355
168356
168357
168358
168359
168360
168361
......
170803
170804
170805
170806
170807
170808
170809

170810

170811
170812
170813
170814
170815
170816
170817
......
172690
172691
172692
172693
172694
172695
172696
172697

172698

172699
172700
172701
172702
172703
172704
172705
......
175596
175597
175598
175599
175600
175601
175602
175603
175604
175605
175606
175607
175608
175609
175610
......
176710
176711
176712
176713
176714
176715
176716
176717
176718
176719
176720
176721
176722
176723
176724
......
176820
176821
176822
176823
176824
176825
176826
176827
176828
176829
176830
176831
176832
176833
176834
......
188620
188621
188622
188623
188624
188625
188626

188627
188628
188629
188630
188631
188632
188633
......
199679
199680
199681
199682
199683
199684
199685
199686
199687
199688
199689
199690
199691
199692
199693
......
199694
199695
199696
199697
199698
199699
199700
199701
199702
199703
199704
199705
199706
199707
199708
......
212029
212030
212031
212032
212033
212034
212035
212036

212037
212038
212039
212040
212041
212042
212043
212044
212045
212046
212047
212048
212049
......
217072
217073
217074
217075
217076
217077
217078
217079
217080
217081
217082
217083
217084
217085
217086
......
221836
221837
221838
221839
221840
221841
221842
221843
221844
221845
221846
221847
221848
221849
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.27.1.  By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
................................................................................
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.27.1"
#define SQLITE_VERSION_NUMBER 3027001
#define SQLITE_SOURCE_ID      "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
................................................................................
** does not affect the value returned by sqlite3_total_changes().
** 
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers 
** are not counted.
**
** This the [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D.  Any changes by other database connections are ignored.
** To detect changes against a database file from other database
** connections use the [PRAGMA data_version] command or the
** [SQLITE_FCNTL_DATA_VERSION] [file control].
** 
** If a separate thread makes changes on the same database connection
................................................................................
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);













/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite3_step(S)] but has neither run to completion (returned
................................................................................
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to bind API fails.


** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
................................................................................
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** a NULL pointer is returned.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   of the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function, an
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
................................................................................
#define OP_OpenPseudo    116 /* synopsis: P3 columns in r[P2]              */
#define OP_Close         117
#define OP_ColumnsUsed   118
#define OP_SeekHit       119 /* synopsis: seekHit=P2                       */
#define OP_Sequence      120 /* synopsis: r[P2]=cursor[P1].ctr++           */
#define OP_NewRowid      121 /* synopsis: r[P2]=rowid                      */
#define OP_Insert        122 /* synopsis: intkey=r[P3] data=r[P2]          */
#define OP_InsertInt     123 /* synopsis: intkey=P3 data=r[P2]             */
#define OP_Delete        124
#define OP_ResetCount    125
#define OP_SorterCompare 126 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
#define OP_SorterData    127 /* synopsis: r[P2]=data                       */
#define OP_RowData       128 /* synopsis: r[P2]=data                       */
#define OP_Rowid         129 /* synopsis: r[P2]=rowid                      */
#define OP_NullRow       130
#define OP_SeekEnd       131
#define OP_SorterInsert  132 /* synopsis: key=r[P2]                        */
#define OP_IdxInsert     133 /* synopsis: key=r[P2]                        */
#define OP_IdxDelete     134 /* synopsis: key=r[P2@P3]                     */
#define OP_DeferredSeek  135 /* synopsis: Move P3 to P1.rowid if needed    */
#define OP_IdxRowid      136 /* synopsis: r[P2]=rowid                      */
#define OP_Destroy       137
#define OP_Clear         138
#define OP_ResetSorter   139
#define OP_CreateBtree   140 /* synopsis: r[P2]=root iDb=P1 flags=P3       */

#define OP_Real          141 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
#define OP_SqlExec       142
#define OP_ParseSchema   143
#define OP_LoadAnalysis  144
#define OP_DropTable     145
#define OP_DropIndex     146
#define OP_DropTrigger   147
#define OP_IntegrityCk   148
#define OP_RowSetAdd     149 /* synopsis: rowset(P1)=r[P2]                 */
#define OP_Param         150
#define OP_FkCounter     151 /* synopsis: fkctr[P1]+=P2                    */
#define OP_MemMax        152 /* synopsis: r[P1]=max(r[P1],r[P2])           */
#define OP_OffsetLimit   153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
#define OP_AggInverse    154 /* synopsis: accum=r[P3] inverse(r[P2@P5])    */
#define OP_AggStep       155 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_AggStep1      156 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_AggValue      157 /* synopsis: r[P3]=value N=P2                 */
#define OP_AggFinal      158 /* synopsis: accum=r[P1] N=P2                 */
#define OP_Expire        159
#define OP_TableLock     160 /* synopsis: iDb=P1 root=P2 write=P3          */
#define OP_VBegin        161
#define OP_VCreate       162
#define OP_VDestroy      163
#define OP_VOpen         164
#define OP_VColumn       165 /* synopsis: r[P3]=vcolumn(P2)                */
#define OP_VRename       166
#define OP_Pagecount     167
#define OP_MaxPgcnt      168
#define OP_Trace         169
#define OP_CursorHint    170
#define OP_Noop          171
#define OP_Explain       172
#define OP_Abortable     173

/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */
#define OPFLG_IN1         0x02  /* in1:   P1 is an input */
................................................................................
/*  72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
/*  80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
/*  88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\
/*  96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,\
/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\
/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
/* 168 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,}

/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode.  The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
................................................................................
#endif
  void *pCommitArg;                 /* Argument to xCommitCallback() */
  int (*xCommitCallback)(void*);    /* Invoked at every commit. */
  void *pRollbackArg;               /* Argument to xRollbackCallback() */
  void (*xRollbackCallback)(void*); /* Invoked at every commit. */
  void *pUpdateArg;
  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  void *pPreUpdateArg;          /* First argument to xPreUpdateCallback */
  void (*xPreUpdateCallback)(   /* Registered using sqlite3_preupdate_hook() */
    void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
  );
  PreUpdate *pPreUpdate;        /* Context for active pre-update callback */
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
................................................................................
#ifndef SQLITE_OMIT_SHARED_CACHE
  int nTableLock;        /* Number of locks in aTableLock */
  TableLock *aTableLock; /* Required table locks for shared-cache mode */
#endif
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */

  int addrCrTab;       /* Address of OP_CreateBtree opcode on CREATE TABLE */
  u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */
................................................................................
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
................................................................................
SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
  if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
    db->mallocFailed = 1;
    if( db->nVdbeExec>0 ){
      db->u1.isInterrupted = 1;
    }
    db->lookaside.bDisable++;



  }
}

/*
** This routine reactivates the memory allocator and clears the
** db->mallocFailed flag as necessary.
**
................................................................................

/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
  assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
  p->accError = eError;
  p->nAlloc = 0;
}

/*
** Extra argument values from a PrintfArguments object
*/
static sqlite3_int64 getIntArg(PrintfArguments *p){
  if( p->nArg<=p->nUsed ) return 0;
................................................................................
** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
** Do the size check before the memory allocation to prevent rogue
** SQL from requesting large allocations using the precision or width
** field of the printf() function.
*/
static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
  char *z;

  if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
    setStrAccumError(pAccum, SQLITE_TOOBIG);
    return 0;
  }
  z = sqlite3DbMallocRaw(pAccum->db, n);
  if( z==0 ){
    setStrAccumError(pAccum, SQLITE_NOMEM);
................................................................................
  assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
  if( p->accError ){
    testcase(p->accError==SQLITE_TOOBIG);
    testcase(p->accError==SQLITE_NOMEM);
    return 0;
  }
  if( p->mxAlloc==0 ){
    N = p->nAlloc - p->nChar - 1;
    setStrAccumError(p, SQLITE_TOOBIG);

    return N;
  }else{
    char *zOld = isMalloced(p) ? p->zText : 0;
    i64 szNew = p->nChar;
    szNew += N + 1;
    if( szNew+p->nChar<=p->mxAlloc ){
      /* Force exponential buffer size growth as long as it does not overflow,
      ** to avoid having to call this routine too often */
................................................................................
** Append N bytes of text from z to the StrAccum object.  Increase the
** size of the memory allocation for StrAccum if necessary.
*/
SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
  assert( z!=0 || N==0 );
  assert( p->zText!=0 || p->nChar==0 || p->accError );
  assert( N>=0 );
  assert( p->accError==0 || p->nAlloc==0 );
  if( p->nChar+N >= p->nAlloc ){
    enlargeAndAppend(p,z,N);
  }else if( N ){
    assert( p->zText );
    p->nChar += N;
    memcpy(&p->zText[p->nChar-N], z, N);
  }
................................................................................
    /* 116 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
    /* 117 */ "Close"            OpHelp(""),
    /* 118 */ "ColumnsUsed"      OpHelp(""),
    /* 119 */ "SeekHit"          OpHelp("seekHit=P2"),
    /* 120 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
    /* 121 */ "NewRowid"         OpHelp("r[P2]=rowid"),
    /* 122 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
    /* 123 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
    /* 124 */ "Delete"           OpHelp(""),
    /* 125 */ "ResetCount"       OpHelp(""),
    /* 126 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
    /* 127 */ "SorterData"       OpHelp("r[P2]=data"),
    /* 128 */ "RowData"          OpHelp("r[P2]=data"),
    /* 129 */ "Rowid"            OpHelp("r[P2]=rowid"),
    /* 130 */ "NullRow"          OpHelp(""),
    /* 131 */ "SeekEnd"          OpHelp(""),
    /* 132 */ "SorterInsert"     OpHelp("key=r[P2]"),
    /* 133 */ "IdxInsert"        OpHelp("key=r[P2]"),
    /* 134 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
    /* 135 */ "DeferredSeek"     OpHelp("Move P3 to P1.rowid if needed"),
    /* 136 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
    /* 137 */ "Destroy"          OpHelp(""),
    /* 138 */ "Clear"            OpHelp(""),
    /* 139 */ "ResetSorter"      OpHelp(""),
    /* 140 */ "CreateBtree"      OpHelp("r[P2]=root iDb=P1 flags=P3"),

    /* 141 */ "Real"             OpHelp("r[P2]=P4"),
    /* 142 */ "SqlExec"          OpHelp(""),
    /* 143 */ "ParseSchema"      OpHelp(""),
    /* 144 */ "LoadAnalysis"     OpHelp(""),
    /* 145 */ "DropTable"        OpHelp(""),
    /* 146 */ "DropIndex"        OpHelp(""),
    /* 147 */ "DropTrigger"      OpHelp(""),
    /* 148 */ "IntegrityCk"      OpHelp(""),
    /* 149 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
    /* 150 */ "Param"            OpHelp(""),
    /* 151 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
    /* 152 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
    /* 153 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
    /* 154 */ "AggInverse"       OpHelp("accum=r[P3] inverse(r[P2@P5])"),
    /* 155 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
    /* 156 */ "AggStep1"         OpHelp("accum=r[P3] step(r[P2@P5])"),
    /* 157 */ "AggValue"         OpHelp("r[P3]=value N=P2"),
    /* 158 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
    /* 159 */ "Expire"           OpHelp(""),
    /* 160 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
    /* 161 */ "VBegin"           OpHelp(""),
    /* 162 */ "VCreate"          OpHelp(""),
    /* 163 */ "VDestroy"         OpHelp(""),
    /* 164 */ "VOpen"            OpHelp(""),
    /* 165 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
    /* 166 */ "VRename"          OpHelp(""),
    /* 167 */ "Pagecount"        OpHelp(""),
    /* 168 */ "MaxPgcnt"         OpHelp(""),
    /* 169 */ "Trace"            OpHelp(""),
    /* 170 */ "CursorHint"       OpHelp(""),
    /* 171 */ "Noop"             OpHelp(""),
    /* 172 */ "Explain"          OpHelp(""),
    /* 173 */ "Abortable"        OpHelp(""),
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
................................................................................
**   * the database file is open,
**   * there are no dirty pages in the cache, and
**   * the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
  if( pPager->fd->pMethods==0 ) return 0;
  if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;



#ifndef SQLITE_OMIT_WAL
  if( pPager->pWal ){
    u32 iRead = 0;
    int rc;
    rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
    return (rc==SQLITE_OK && iRead==0);
  }
................................................................................
    char *pNew = NULL;             /* New temp space */
    i64 nByte = 0;

    if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
      rc = sqlite3OsFileSize(pPager->fd, &nByte);
    }
    if( rc==SQLITE_OK ){


      pNew = (char *)sqlite3PageMalloc(pageSize);

      if( !pNew ) rc = SQLITE_NOMEM_BKPT;



    }

    if( rc==SQLITE_OK ){
      pager_reset(pPager);
      rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
    }
    if( rc==SQLITE_OK ){
................................................................................
  /* If the cache contains a page with page-number pgno, remove it
  ** from its hash chain. Also, if the PGHDR_NEED_SYNC flag was set for 
  ** page pgno before the 'move' operation, it needs to be retained 
  ** for the page moved there.
  */
  pPg->flags &= ~PGHDR_NEED_SYNC;
  pPgOld = sqlite3PagerLookup(pPager, pgno);
  assert( !pPgOld || pPgOld->nRef==1 );
  if( pPgOld ){




    pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
    if( pPager->tempFile ){
      /* Do not discard pages from an in-memory database since we might
      ** need to rollback later.  Just move the page out of the way. */
      sqlite3PcacheMove(pPgOld, pPager->dbSize+1);
    }else{
      sqlite3PcacheDrop(pPgOld);
................................................................................

/*
** Release a lock obtained by an earlier successful call to
** sqlite3PagerSnapshotCheck().
*/
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){
  assert( pPager->pWal );
  return sqlite3WalSnapshotUnlock(pPager->pWal);
}

#endif /* SQLITE_ENABLE_SNAPSHOT */
#endif /* !SQLITE_OMIT_WAL */

#ifdef SQLITE_ENABLE_ZIPVFS
/*
................................................................................
  u8 hdrOffset;        /* 100 for page 1.  0 otherwise */
  u8 childPtrSize;     /* 0 if leaf==1.  4 if leaf==0 */
  u8 max1bytePayload;  /* min(maxLocal,127) */
  u8 nOverflow;        /* Number of overflow cell bodies in aCell[] */
  u16 maxLocal;        /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
  u16 minLocal;        /* Copy of BtShared.minLocal or BtShared.minLeaf */
  u16 cellOffset;      /* Index in aData of first cell pointer */
  u16 nFree;           /* Number of free bytes on the page */
  u16 nCell;           /* Number of cells on this page, local and ovfl */
  u16 maskPage;        /* Mask for page offset */
  u16 aiOvfl[4];       /* Insert the i-th overflow cell before the aiOvfl-th
                       ** non-overflow cell */
  u8 *apOvfl[4];       /* Pointers to the body of overflow cells */
  BtShared *pBt;       /* Pointer to BtShared that this page is part of */
  u8 *aData;           /* Pointer to disk image of the page data */
................................................................................
  assert( pPage->nOverflow==0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  temp = 0;
  src = data = pPage->aData;
  hdr = pPage->hdrOffset;
  cellOffset = pPage->cellOffset;
  nCell = pPage->nCell;
  assert( nCell==get2byte(&data[hdr+3]) );
  iCellFirst = cellOffset + 2*nCell;
  usableSize = pPage->pBt->usableSize;

  /* This block handles pages with two or fewer free blocks and nMaxFrag
  ** or fewer fragmented bytes. In this case it is faster to move the
  ** two (or one) blocks of cells using memmove() and add the required
  ** offsets to each pointer in the cell-pointer array than it is to 
  ** reconstruct the entire page.  */
  if( (int)data[hdr+7]<=nMaxFrag ){
    int iFree = get2byte(&data[hdr+1]);

    /* If the initial freeblock offset were out of bounds, that would
    ** have been detected by btreeInitPage() when it was computing the
    ** number of free bytes on the page. */
    assert( iFree<=usableSize-4 );
    if( iFree ){
      int iFree2 = get2byte(&data[iFree]);
      if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
      if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
        u8 *pEnd = &data[cellOffset + nCell*2];
................................................................................
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:

  if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( cbrk>=iCellFirst );
  put2byte(&data[hdr+5], cbrk);
  data[hdr+1] = 0;
  data[hdr+2] = 0;
................................................................................
** detected then *pRc is set to SQLITE_CORRUPT and NULL is returned.
**
** Slots on the free list that are between 1 and 3 bytes larger than nByte
** will be ignored if adding the extra space to the fragmentation count
** causes the fragmentation count to exceed 60.
*/
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
  const int hdr = pPg->hdrOffset;
  u8 * const aData = pPg->aData;
  int iAddr = hdr + 1;
  int pc = get2byte(&aData[iAddr]);
  int x;
  int usableSize = pPg->pBt->usableSize;
  int size;            /* Size of the free slot */

  assert( pc>0 );
  while( pc<=usableSize-4 ){
    /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
    ** freeblock form a big-endian integer which is the size of the freeblock
    ** in bytes, including the 4-byte header. */
    size = get2byte(&aData[pc+2]);
    if( (x = size - nByte)>=0 ){
      testcase( x==4 );
      testcase( x==3 );
      if( size+pc > usableSize ){
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
        return 0;
      }else if( x<4 ){
        /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
        ** number of bytes in fragments may not exceed 60. */
        if( aData[hdr+7]>57 ) return 0;

        /* Remove the slot from the free-list. Update the number of
        ** fragmented bytes within the page. */
        memcpy(&aData[iAddr], &aData[pc], 2);
        aData[hdr+7] += (u8)x;




      }else{
        /* The slot remains on the free-list. Reduce its size to account
         ** for the portion used by the new allocation. */
        put2byte(&aData[pc+2], x);
      }
      return &aData[pc + x];
    }
    iAddr = pc;
    pc = get2byte(&aData[pc]);
    if( pc<iAddr+size ) break;
  }
  if( pc ){

    *pRc = SQLITE_CORRUPT_PAGE(pPg);
  }







  return 0;
}

/*
** Allocate nByte bytes of space from within the B-Tree page passed
** as the first argument. Write into *pIdx the index into pPage->aData[]
** of the first byte of allocated space. Return either SQLITE_OK or
................................................................................
    if( top==0 && pPage->pBt->usableSize==65536 ){
      top = 65536;
    }else{
      return SQLITE_CORRUPT_PAGE(pPage);
    }
  }

  /* If there is enough space between gap and top for one more cell pointer
  ** array entry offset, and if the freelist is not empty, then search the
  ** freelist looking for a free slot big enough to satisfy the request.
  */
  testcase( gap+2==top );
  testcase( gap+1==top );
  testcase( gap==top );
  if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
    u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
    if( pSpace ){
................................................................................

  /* The request could not be fulfilled using a freelist slot.  Check
  ** to see if defragmentation is necessary.
  */
  testcase( gap+2+nByte==top );
  if( gap+2+nByte>top ){
    assert( pPage->nCell>0 || CORRUPT_DB );

    rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
    if( rc ) return rc;
    top = get2byteNotZero(&data[hdr+5]);
    assert( gap+2+nByte<=top );
  }


  /* Allocate memory from the gap in between the cell pointer array
  ** and the cell content area.  The btreeInitPage() call has already
  ** validated the freelist.  Given that the freelist is valid, there
  ** is no way that the allocation can extend off the end of the page.
  ** The assert() below verifies the previous sentence.
  */
  top -= nByte;
  put2byte(&data[hdr+5], top);
  assert( top+nByte <= (int)pPage->pBt->usableSize );
................................................................................
/*
** Return a section of the pPage->aData to the freelist.
** The first byte of the new free block is pPage->aData[iStart]
** and the size of the block is iSize bytes.
**
** Adjacent freeblocks are coalesced.
**
** Note that even though the freeblock list was checked by btreeInitPage(),
** that routine will not detect overlap between cells or freeblocks.  Nor
** does it detect cells or freeblocks that encrouch into the reserved bytes
** at the end of the page.  So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
  u16 iPtr;                             /* Address of ptr to next freeblock */
................................................................................
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  pPage->max1bytePayload = pBt->max1bytePayload;
  return SQLITE_OK;
}

/*
** Initialize the auxiliary information for a disk block.
**
** Return SQLITE_OK on success.  If we see that the page does
** not contain a well-formed database page, then return 
** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed.  It only shows that
** we failed to detect any corruption.
*/

static int btreeInitPage(MemPage *pPage){
  int pc;            /* Address of a freeblock within pPage->aData[] */
  u8 hdr;            /* Offset to beginning of page header */
  u8 *data;          /* Equal to pPage->aData */
  BtShared *pBt;        /* The main btree structure */
  int usableSize;    /* Amount of usable space on each page */
  u16 cellOffset;    /* Offset from start of page to first cell pointer */
  int nFree;         /* Number of unused bytes on the page */
  int top;           /* First byte of the cell content area */
  int iCellFirst;    /* First allowable cell or freeblock offset */
  int iCellLast;     /* Last possible cell or freeblock offset */

  assert( pPage->pBt!=0 );
  assert( pPage->pBt->db!=0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  assert( pPage->isInit==0 );


  pBt = pPage->pBt;
  hdr = pPage->hdrOffset;
  data = pPage->aData;
  /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
  ** the b-tree page type. */
  if( decodeFlags(pPage, data[hdr]) ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  pPage->maskPage = (u16)(pBt->pageSize - 1);
  pPage->nOverflow = 0;
  usableSize = pBt->usableSize;
  pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
  pPage->aDataEnd = &data[usableSize];
  pPage->aCellIdx = &data[cellOffset];
  pPage->aDataOfst = &data[pPage->childPtrSize];
  /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
  ** the start of the cell content area. A zero value for this integer is
  ** interpreted as 65536. */
  top = get2byteNotZero(&data[hdr+5]);

  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  ** number of cells on the page. */
  pPage->nCell = get2byte(&data[hdr+3]);
  if( pPage->nCell>MX_CELL(pBt) ){
    /* To many cells for a single page.  The page must be corrupt */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  testcase( pPage->nCell==MX_CELL(pBt) );
  /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
  ** possible for a root page of a table that contains no rows) then the
  ** offset to the cell content area will equal the page size minus the
  ** bytes of reserved space. */
  assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );

  /* A malformed database page might cause us to read past the end
  ** of page when parsing a cell.  
  **
  ** The following block of code checks early to see if a cell extends
  ** past the end of a page boundary and causes SQLITE_CORRUPT to be 
  ** returned if it does.
  */
  iCellFirst = cellOffset + 2*pPage->nCell;
  iCellLast = usableSize - 4;
  if( pBt->db->flags & SQLITE_CellSizeCk ){
    int i;            /* Index into the cell pointer array */
    int sz;           /* Size of a cell */

    if( !pPage->leaf ) iCellLast--;
    for(i=0; i<pPage->nCell; i++){
      pc = get2byteAligned(&data[cellOffset+i*2]);
      testcase( pc==iCellFirst );
      testcase( pc==iCellLast );
      if( pc<iCellFirst || pc>iCellLast ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
      sz = pPage->xCellSize(pPage, &data[pc]);
      testcase( pc+sz==usableSize );
      if( pc+sz>usableSize ){
        return SQLITE_CORRUPT_PAGE(pPage);
      }
    }
    if( !pPage->leaf ) iCellLast++;
  }  

  /* Compute the total free space on the page
  ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
  ** start of the first freeblock on the page, or is zero if there are no
  ** freeblocks. */
  pc = get2byte(&data[hdr+1]);
  nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
................................................................................
  ** serves to verify that the offset to the start of the cell-content
  ** area, according to the page header, lies within the page.
  */
  if( nFree>usableSize ){
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  pPage->nFree = (u16)(nFree - iCellFirst);


























































































  pPage->isInit = 1;



  return SQLITE_OK;
}

/*
** Set up a raw page so that it looks like a database page holding
** no entries.
*/
................................................................................
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( pCur==0 || ppPage==&pCur->pPage );
  assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
  assert( pCur==0 || pCur->iPage>0 );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
    goto getAndInitPage_error;
  }
  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
  if( rc ){
    goto getAndInitPage_error;
  }
  *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  if( (*ppPage)->isInit==0 ){
    btreePageFromDbPage(pDbPage, pgno, pBt);
    rc = btreeInitPage(*ppPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
      goto getAndInitPage_error;
    }
  }
  assert( (*ppPage)->pgno==pgno );
  assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );

  /* If obtaining a child page for a cursor, we must verify that the page is
  ** compatible with the root page. */
  if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
    rc = SQLITE_CORRUPT_PGNO(pgno);
    releasePage(*ppPage);
    goto getAndInitPage_error;
  }
  return SQLITE_OK;

getAndInitPage_error:


  if( pCur ){
    pCur->iPage--;
    pCur->pPage = pCur->apPage[pCur->iPage];
  }
  testcase( pgno==0 );
  assert( pgno!=0 || rc==SQLITE_CORRUPT );
  return rc;
................................................................................
          pCur->ix = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
          pCur->curFlags &= ~BTCF_ValidOvfl;
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey);
          sqlite3_free(pCellKey);
        }
        assert( 
            (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
         && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
        );
        if( c<0 ){
................................................................................
  int hdr;        /* Beginning of the header.  0 most pages.  100 page 1 */

  if( *pRC ) return;
  assert( idx>=0 && idx<pPage->nCell );
  assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );

  data = pPage->aData;
  ptr = &pPage->aCellIdx[2*idx];
  pc = get2byte(ptr);
  hdr = pPage->hdrOffset;
  testcase( pc==get2byte(&data[hdr+5]) );
  testcase( pc+sz==pPage->pBt->usableSize );
  if( pc+sz > pPage->pBt->usableSize ){
................................................................................
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  /* The cell should normally be sized correctly.  However, when moving a
  ** malformed cell from a leaf page to an interior page, if the cell size
  ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
  ** might be less than 8 (leaf-size + pointer) on the interior node.  Hence
  ** the term after the || in the following assert(). */
  assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );

  if( pPage->nOverflow || sz+2>pPage->nFree ){
    if( pTemp ){
      memcpy(pTemp, pCell, sz);
      pCell = pTemp;
    }
    if( iChild ){
      put4byte(pCell, iChild);
................................................................................
    }
    pIns = pPage->aCellIdx + i*2;
    memmove(pIns+2, pIns, 2*(pPage->nCell - i));
    put2byte(pIns, idx);
    pPage->nCell++;
    /* increment the cell count */
    if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
    assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell );
#ifndef SQLITE_OMIT_AUTOVACUUM
    if( pPage->pBt->autoVacuum ){
      /* The cell may contain a pointer to an overflow page. If so, write
      ** the entry for the overflow page into the pointer map.
      */
      ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
    }
................................................................................
**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
**    ixNx[4] = Total number of cells.
**
** For a table-btree, the concept is similar, except only apEnd[0]..apEnd[2]
** are used and they point to the leaf pages only, and the ixNx value are:
**
**    ixNx[0] = Number of cells in Child-1.
**    ixNx[1] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
**    ixNx[2] = Number of cells in Child-1 and Child-2 + both divider cells





*/
typedef struct CellArray CellArray;
struct CellArray {
  int nCell;              /* Number of cells in apCell[] */
  MemPage *pRef;          /* Reference page */
  u8 **apCell;            /* All cells begin balanced */
  u16 *szCell;            /* Local size of all cells in apCell[] */
................................................................................
  }

  /* Add any overflow cells */
  for(i=0; i<pPg->nOverflow; i++){
    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
    if( iCell>=0 && iCell<nNew ){
      pCellptr = &pPg->aCellIdx[iCell * 2];
      assert( nCell>=iCell );
      memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);

      nCell++;
      if( pageInsertArray(
            pPg, pBegin, &pData, pCellptr,
            iCell+iNew, 1, pCArray
      ) ) goto editpage_fail;
    }
  }
................................................................................
  MemPage *pNew;                       /* Newly allocated page */
  int rc;                              /* Return Code */
  Pgno pgnoNew;                        /* Page number of pNew */

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  assert( pPage->nOverflow==1 );

  if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;  /* dbfuzz001.test */



  /* Allocate a new page. This page will become the right-sibling of 
  ** pPage. Make the parent page writable, so that the new divider cell
  ** may be inserted. If both these operations are successful, proceed.
  */
  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);

................................................................................
    /* Reinitialize page pTo so that the contents of the MemPage structure
    ** match the new data. The initialization of pTo can actually fail under
    ** fairly obscure circumstances, even though it is a copy of initialized 
    ** page pFrom.
    */
    pTo->isInit = 0;
    rc = btreeInitPage(pTo);

    if( rc!=SQLITE_OK ){
      *pRC = rc;
      return;
    }
  
    /* If this is an auto-vacuum database, update the pointer-map entries
    ** for any b-tree or overflow pages that pTo now contains the pointers to.
................................................................................
  */
  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
  assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );

  if( !aOvflSpace ){
    return SQLITE_NOMEM_BKPT;
  }


  /* Find the sibling pages to balance. Also locate the cells in pParent 
  ** that divide the siblings. An attempt is made to find NN siblings on 
  ** either side of pPage. More siblings are taken from one side, however, 
  ** if there are fewer than NN siblings on the other side. If pParent
  ** has NB or fewer children then all children of pParent are taken.  
  **
................................................................................
  pgno = get4byte(pRight);
  while( 1 ){
    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
    if( rc ){
      memset(apOld, 0, (i+1)*sizeof(MemPage*));
      goto balance_cleanup;
    }







    nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
    if( (i--)==0 ) break;

    if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
      apDiv[i] = pParent->apOvfl[0];
      pgno = get4byte(apDiv[i]);
      szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
................................................................................
  ** 
  */
  usableSpace = pBt->usableSize - 12 + leafCorrection;
  for(i=k=0; i<nOld; i++, k++){
    MemPage *p = apOld[i];
    b.apEnd[k] = p->aDataEnd;
    b.ixNx[k] = cntOld[i];



    if( !leafData ){
      k++;
      b.apEnd[k] = pParent->aDataEnd;
      b.ixNx[k] = cntOld[i]+1;
    }

    szNew[i] = usableSpace - p->nFree;
    for(j=0; j<p->nOverflow; j++){
      szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
    }
    cntNew[i] = cntOld[i];
  }
  k = nOld;
................................................................................
  ** associated with the right-child of each sibling may also need to be 
  ** updated. This happens below, after the sibling pages have been 
  ** populated, not here.
  */
  if( ISAUTOVACUUM ){
    MemPage *pOld;
    MemPage *pNew = pOld = apNew[0];
    u8 *aOld = pNew->aData;
    int cntOldNext = pNew->nCell + pNew->nOverflow;
    int usableSize = pBt->usableSize;
    int iNew = 0;
    int iOld = 0;

    for(i=0; i<b.nCell; i++){
      u8 *pCell = b.apCell[i];
      if( i==cntOldNext ){


        pOld = (++iOld)<nNew ? apNew[iOld] : apOld[iOld];
        cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
        aOld = pOld->aData;
      }
      if( i==cntNew[iNew] ){
        pNew = apNew[++iNew];
        if( !leafData ) continue;
      }

      /* Cell pCell is destined for new sibling page pNew. Originally, it
................................................................................
      ** was either part of sibling page iOld (possibly an overflow cell), 
      ** or else the divider cell to the left of sibling page iOld. So,
      ** if sibling page iOld had the same page number as pNew, and if
      ** pCell really was a part of sibling page iOld (not a divider or
      ** overflow cell), we can skip updating the pointer map entries.  */
      if( iOld>=nNew
       || pNew->pgno!=aPgno[iOld]
       || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize])
      ){
        if( !leafCorrection ){
          ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc);
        }
        if( cachedCellSize(&b,i)>pNew->minLocal ){
          ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
        }
................................................................................
  if( rc ){
    *ppChild = 0;
    releasePage(pChild);
    return rc;
  }
  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
  assert( pChild->nCell==pRoot->nCell );

  TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));

  /* Copy the overflow cells from pRoot to pChild */
  memcpy(pChild->aiOvfl, pRoot->aiOvfl,
         pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
  memcpy(pChild->apOvfl, pRoot->apOvfl,
................................................................................
  VVA_ONLY( int balance_quick_called = 0 );
  VVA_ONLY( int balance_deeper_called = 0 );

  do {
    int iPage = pCur->iPage;
    MemPage *pPage = pCur->pPage;


    if( iPage==0 ){
      if( pPage->nOverflow ){
        /* The root page of the b-tree is overfull. In this case call the
        ** balance_deeper() function to create a new child for the root-page
        ** and copy the current contents of the root-page to it. The
        ** next iteration of the do-loop will balance the child page.
        */ 
................................................................................
    }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
      break;
    }else{
      MemPage * const pParent = pCur->apPage[iPage-1];
      int const iIdx = pCur->aiIdx[iPage-1];

      rc = sqlite3PagerWrite(pParent->pDbPage);



      if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_QUICKBALANCE
        if( pPage->intKeyLeaf
         && pPage->nOverflow==1
         && pPage->aiOvfl[0]==pPage->nCell
         && pParent->pgno!=1
         && pParent->nCell==iIdx
................................................................................

  }
  assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );

  pPage = pCur->pPage;
  assert( pPage->intKey || pX->nKey>=0 );
  assert( pPage->leaf || !pPage->intKey );





  TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
          pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
          loc==0 ? "overwrite" : "new entry"));
  assert( pPage->isInit );
  newCell = pBt->pTmpSpace;
  assert( newCell!=0 );
................................................................................
  assert( pCur->eState==CURSOR_VALID );
  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );

  iCellDepth = pCur->iPage;
  iCellIdx = pCur->ix;
  pPage = pCur->pPage;
  pCell = findCell(pPage, iCellIdx);


  /* If the bPreserve flag is set to true, then the cursor position must
  ** be preserved following this delete operation. If the current delete
  ** will cause a b-tree rebalance, then this is done by saving the cursor
  ** key and leaving the cursor in CURSOR_REQUIRESEEK state before 
  ** returning. 
  **
................................................................................
  ** node to replace the deleted cell.  */
  if( !pPage->leaf ){
    MemPage *pLeaf = pCur->pPage;
    int nCell;
    Pgno n;
    unsigned char *pTmp;





    if( iCellDepth<pCur->iPage-1 ){
      n = pCur->apPage[iCellDepth+1]->pgno;
    }else{
      n = pCur->pPage->pgno;
    }
    pCell = findCell(pLeaf, pLeaf->nCell-1);
    if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
................................................................................
  int rc;
  MemPage *pPage = 0;
  BtShared *pBt = p->pBt;

  assert( sqlite3BtreeHoldsMutex(p) );
  assert( p->inTrans==TRANS_WRITE );
  assert( iTable>=2 );




  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
  if( rc ) return rc;
  rc = sqlite3BtreeClearTable(p, iTable, 0);
  if( rc ){
    releasePage(pPage);
    return rc;
................................................................................
** Check the integrity of the freelist or of an overflow page list.
** Verify that the number of pages on the list is N.
*/
static void checkList(
  IntegrityCk *pCheck,  /* Integrity checking context */
  int isFreeList,       /* True for a freelist.  False for overflow page list */
  int iPage,            /* Page number for first page in the list */
  int N                 /* Expected number of pages in the list */
){
  int i;
  int expected = N;
  int nErrAtStart = pCheck->nErr;
  while( iPage!=0 && pCheck->mxErr ){
    DbPage *pOvflPage;
    unsigned char *pOvflData;
    if( checkRef(pCheck, iPage) ) break;
    N--;
    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
................................................................................
  pPage->isInit = 0;
  if( (rc = btreeInitPage(pPage))!=0 ){
    assert( rc==SQLITE_CORRUPT );  /* The only possible error from InitPage */
    checkAppendMsg(pCheck,
                   "btreeInitPage() returns error code %d", rc);
    goto end_of_check;
  }





  data = pPage->aData;
  hdr = pPage->hdrOffset;

  /* Set up for cell analysis */
  pCheck->zPfx = "On tree page %d cell %d: ";
  contentOffset = get2byteNotZero(&data[hdr+5]);
  assert( contentOffset<=usableSize );  /* Enforced by btreeInitPage() */
................................................................................
      }
      maxKey = info.nKey;
      keyCanBeEqual = 0;     /* Only the first key on the page may ==maxKey */
    }

    /* Check the content overflow list */
    if( info.nPayload>info.nLocal ){
      int nPage;       /* Number of pages on the overflow chain */
      Pgno pgnoOvfl;   /* First page of the overflow chain */
      assert( pc + info.nSize - 4 <= usableSize );
      nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
      pgnoOvfl = get4byte(&pCell[info.nSize - 4]);
#ifndef SQLITE_OMIT_AUTOVACUUM
      if( pBt->autoVacuum ){
        checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage);
................................................................................
    ** EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
    ** is the offset of the first freeblock, or zero if there are no
    ** freeblocks on the page. 
    */
    i = get2byte(&data[hdr+1]);
    while( i>0 ){
      int size, j;
      assert( (u32)i<=usableSize-4 );     /* Enforced by btreeInitPage() */
      size = get2byte(&data[i+2]);
      assert( (u32)(i+size)<=usableSize );  /* Enforced by btreeInitPage() */
      btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
      /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
      ** big-endian integer which is the offset in the b-tree page of the next
      ** freeblock in the chain, or zero if the freeblock is the last on the
      ** chain. */
      j = get2byte(&data[i]);
      /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
      ** increasing offset. */
      assert( j==0 || j>i+size );  /* Enforced by btreeInitPage() */
      assert( (u32)j<=usableSize-4 );   /* Enforced by btreeInitPage() */
      i = j;
    }
    /* Analyze the min-heap looking for overlap between cells and/or 
    ** freeblocks, and counting the number of untracked bytes in nFrag.
    ** 
    ** Each min-heap entry is of the form:    (start_address<<16)|end_address.
    ** There is an implied first entry the covers the page header, the cell
................................................................................
  assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
  assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
  return rc;
#endif
}

/*
** Make sure pMem->z points to a writable allocation of at least 
** min(n,32) bytes.
**
** If the bPreserve argument is true, then copy of the content of
** pMem->z into the new allocation.  pMem must be either a string or
** blob if bPreserve is true.  If bPreserve is false, any prior content
** in pMem->z is discarded.
*/
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
................................................................................
  /* If the bPreserve flag is set to true, then the memory cell must already
  ** contain a valid string or blob value.  */
  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
  testcase( bPreserve && pMem->z==0 );

  assert( pMem->szMalloc==0
       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
  if( n<32 ) n = 32;
  if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
    pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    bPreserve = 0;
  }else{
    if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
    pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
  }
................................................................................
    iLimit = SQLITE_MAX_LENGTH;
  }
  flags = (enc==0?MEM_Blob:MEM_Str);
  if( nByte<0 ){
    assert( enc!=0 );
    if( enc==SQLITE_UTF8 ){
      nByte = 0x7fffffff & (int)strlen(z);
      if( nByte>iLimit ) nByte = iLimit+1;
    }else{
      for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
    }
    flags |= MEM_Term;
  }

  /* The following block sets the new values of Mem.z and Mem.xDel. It
  ** also sets a flag in local variable "flags" to indicate the memory
  ** management (one of MEM_Dyn or MEM_Static).
  */
  if( xDel==SQLITE_TRANSIENT ){
    int nAlloc = nByte;
    if( flags&MEM_Term ){
      nAlloc += (enc==SQLITE_UTF8?1:2);
    }
    if( nByte>iLimit ){
      return SQLITE_TOOBIG;
    }
    testcase( nAlloc==0 );
    testcase( nAlloc==31 );
    testcase( nAlloc==32 );
    if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){
      return SQLITE_NOMEM_BKPT;
    }
    memcpy(pMem->z, z, nAlloc);
  }else if( xDel==SQLITE_DYNAMIC ){
    sqlite3VdbeMemRelease(pMem);
    pMem->zMalloc = pMem->z = (char *)z;
    pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
  }else{
    sqlite3VdbeMemRelease(pMem);
    pMem->z = (char *)z;




    pMem->xDel = xDel;
    flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);

  }

  pMem->n = nByte;
  pMem->flags = flags;
  pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);

#ifndef SQLITE_OMIT_UTF16
................................................................................
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
     || opcode==OP_VDestroy

     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
    if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
................................................................................
**    3      The name of the table that the column derives from
**    4      The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
  sqlite3_stmt *pStmt,
  int N,
  const void *(*xFunc)(Mem*),
  int useType
){
  const void *ret;
  Vdbe *p;
  int n;
  sqlite3 *db;
#ifdef SQLITE_ENABLE_API_ARMOR
  if( pStmt==0 ){
................................................................................
  db = p->db;
  assert( db!=0 );
  n = sqlite3_column_count(pStmt);
  if( N<n && N>=0 ){
    N += useType*n;
    sqlite3_mutex_enter(db->mutex);
    assert( db->mallocFailed==0 );






    ret = xFunc(&p->aColName[N]);

     /* A malloc may have failed inside of the xFunc() call. If this
    ** is the case, clear the mallocFailed flag and return NULL.
    */
    if( db->mallocFailed ){
      sqlite3OomClear(db);
      ret = 0;
    }
    sqlite3_mutex_leave(db->mutex);
................................................................................
}

/*
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
}
#endif

/*
** Constraint:  If you have ENABLE_COLUMN_METADATA then you must
** not define OMIT_DECLTYPE.
*/
................................................................................

#ifndef SQLITE_OMIT_DECLTYPE
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_DECLTYPE */

#ifdef SQLITE_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
}
#endif /* SQLITE_OMIT_UTF16 */

/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_ENABLE_COLUMN_METADATA */


/******************************* sqlite3_bind_  ***************************
** 
................................................................................
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}









/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
  Vdbe *v = (Vdbe*)pStmt;
  return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
}
................................................................................
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
#endif
  /*** INSERT STACK UNION HERE ***/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  sqlite3VdbeEnter(p);









  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
  assert( p->bIsReader || p->readOnly!=0 );
  p->iCurrentTime = 0;
  assert( p->explain==0 );
  p->pResultSet = 0;
  db->busyHandler.nBusy = 0;
  if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
  sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  if( db->xProgress ){
    u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
    assert( 0 < db->nProgressOps );
    nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
  }else{
    nProgressLimit = 0xffffffff;
  }
#endif
#ifdef SQLITE_DEBUG
  sqlite3BeginBenignMalloc();
  if( p->pc==0
   && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
  ){
    int i;
    int once = 1;
................................................................................
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  /* Call the progress callback if it is configured and the required number
  ** of VDBE ops have been executed (either since this invocation of
  ** sqlite3VdbeExec() or since last time the progress callback was called).
  ** If the progress callback returns non-zero, exit the virtual machine with
  ** a return code SQLITE_ABORT.
  */
  if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
    assert( db->nProgressOps!=0 );
    nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
    if( db->xProgress(db->pProgressArg) ){

      rc = SQLITE_INTERRUPT;
      goto abort_due_to_error;
    }
  }
#endif
  
  break;
................................................................................
  pOp->opcode = OP_String;
  pOp->p1 = sqlite3Strlen30(pOp->p4.z);

#ifndef SQLITE_OMIT_UTF16
  if( encoding!=SQLITE_UTF8 ){
    rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
    assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG );

    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
    assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z );
    assert( VdbeMemDynamic(pOut)==0 );
    pOut->szMalloc = 0;
    pOut->flags |= MEM_Static;
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite3DbFree(db, pOp->p4.z);
    }
    pOp->p4type = P4_DYNAMIC;
    pOp->p4.z = pOut->z;
    pOp->p1 = pOut->n;
  }
  testcase( rc==SQLITE_TOOBIG );
#endif
  if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
    goto too_big;
  }
  assert( rc==SQLITE_OK );
  /* Fall through to the next case, OP_String */
}
................................................................................
*/
case OP_ResultRow: {
  Mem *pMem;
  int i;
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 );
  assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  /* Run the progress counter just before returning.
  */
  if( db->xProgress!=0
   && nVmStep>=nProgressLimit 
   && db->xProgress(db->pProgressArg)!=0
  ){
    rc = SQLITE_INTERRUPT;
    goto abort_due_to_error;
  }
#endif

  /* If this statement has violated immediate foreign key constraints, do
  ** not return the number of rows modified. And do not RELEASE the statement
  ** transaction. It needs to be rolled back.  */
  if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
    assert( db->flags&SQLITE_CountRows );
    assert( p->usesStmtJournal );
................................................................................
    op_column_read_header:
      i = pC->nHdrParsed;
      offset64 = aOffset[i];
      zHdr = zData + pC->iHdrOffset;
      zEndHdr = zData + aOffset[0];
      testcase( zHdr>=zEndHdr );
      do{
        if( (t = zHdr[0])<0x80 ){
          zHdr++;
          offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
        }else{
          zHdr += sqlite3GetVarint32(zHdr, &t);

          offset64 += sqlite3VdbeSerialTypeLen(t);
        }
        pC->aType[i++] = t;
        aOffset[i] = (u32)(offset64 & 0xffffffff);
      }while( i<=p2 && zHdr<zEndHdr );

      /* The record is corrupt if any of the following are true:
      ** (1) the bytes of the header extend past the declared header size
      ** (2) the entire header was used but not all data was used
      ** (3) the end of the data extends beyond the end of the record.
      */
................................................................................
** and register P2 becomes ephemeral.  If the cursor is changed, the
** value of register P2 will then change.  Make sure this does not
** cause any problems.)
**
** This instruction only works on tables.  The equivalent instruction
** for indices is OP_IdxInsert.
*/
/* Opcode: InsertInt P1 P2 P3 P4 P5
** Synopsis: intkey=P3 data=r[P2]
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
*/
case OP_Insert: 
case OP_InsertInt: {
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int seekResult;   /* Result of prior seek or 0 if no USESEEKRESULT flag */
  const char *zDb;  /* database name - used by the update hook */
  Table *pTab;      /* Table structure - used by update and pre-update hooks */
  BtreePayload x;   /* Payload to be inserted */
................................................................................
  assert( pC->eCurType==CURTYPE_BTREE );
  assert( pC->uc.pCursor!=0 );
  assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
  assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
  REGISTER_TRACE(pOp->p2, pData);
  sqlite3VdbeIncrWriteCounter(p, pC);

  if( pOp->opcode==OP_Insert ){
    pKey = &aMem[pOp->p3];
    assert( pKey->flags & MEM_Int );
    assert( memIsValid(pKey) );
    REGISTER_TRACE(pOp->p3, pKey);
    x.nKey = pKey->u.i;
  }else{
    assert( pOp->opcode==OP_InsertInt );
    x.nKey = pOp->p3;
  }

  if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
    assert( pC->iDb>=0 );
    zDb = db->aDb[pC->iDb].zDbSName;
    pTab = pOp->p4.pTab;
    assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
  }else{
................................................................................
    for(i=0; i<p->nMem; i++){
      aMem[i].pScopyFrom = 0;  /* Prevent false-positive AboutToChange() errs */
      aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
    }
  }
#endif
  pOp = &aOp[-1];

  break;
}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
................................................................................
    sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
  testcase( nVmStep>0 );









  p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
  sqlite3VdbeLeave(p);
  assert( rc!=SQLITE_OK || nExtraDelete==0 
       || sqlite3_strlike("DELETE%",p->zSql,0)!=0 
  );
  return rc;

................................................................................
      resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
                   zType,0);
    }
  }
  return 0;
}

































/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
** The Name context of the SELECT statement is pNC.  zType is either
** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
**
** This routine resolves each term of the clause into an expression.
** If the order-by term is an integer I between 1 and N (where N is the
................................................................................
    /* Otherwise, treat the ORDER BY term as an ordinary expression */
    pItem->u.x.iOrderByCol = 0;
    if( sqlite3ResolveExprNames(pNC, pE) ){
      return 1;
    }
    for(j=0; j<pSelect->pEList->nExpr; j++){
      if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
        if( ExprHasProperty(pE, EP_WinFunc) ){
          /* Since this window function is being changed into a reference

          ** to the same window function the result set, remove the instance
          ** of this window function from the Select.pWin list. */

          Window **pp;
          for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
            if( *pp==pE->y.pWin ){
              *pp = (*pp)->pNextWin;
            }    
          }
        }
#endif
        pItem->u.x.iOrderByCol = j+1;
      }
    }
  }
  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
}

................................................................................
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }


    if( IN_RENAME_OBJECT ){
      Window *pWin;
      for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
        if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
         || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
        ){
          return WRC_Abort;
        }
      }
    }


    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }
................................................................................
    ** We will have to generate an ephemeral table to do the job.
    */
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( inFlags & IN_INDEX_LOOP ){
      pParse->nQueryLoop = 0;
      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
        eType = IN_INDEX_ROWID;
      }
    }else if( prRhsHasNull ){
      *prRhsHasNull = rMayHaveNull = ++pParse->nMem;
    }
    assert( pX->op==TK_IN );
    sqlite3CodeRhsOfIN(pParse, pX, iTab, eType==IN_INDEX_ROWID);
    if( rMayHaveNull ){
      sqlite3SetHasNullFlag(v, iTab, rMayHaveNull);
    }
    pParse->nQueryLoop = savedNQueryLoop;
  }

  if( aiMap && eType!=IN_INDEX_INDEX_ASC && eType!=IN_INDEX_INDEX_DESC ){
................................................................................
**     x IN (SELECT a FROM b)     -- IN operator with subquery on the right
**
** The pExpr parameter is the IN operator.  The cursor number for the
** constructed ephermeral table is returned.  The first time the ephemeral
** table is computed, the cursor number is also stored in pExpr->iTable,
** however the cursor number returned might not be the same, as it might
** have been duplicated using OP_OpenDup.
**
** If parameter isRowid is non-zero, then LHS of the IN operator is guaranteed
** to be a non-null integer. In this case, the ephemeral table can be an
** table B-Tree that keyed by only integers.  The more general cases uses
** an index B-Tree which can have arbitrary keys, but is slower to both
** read and write.
**
** If the LHS expression ("x" in the examples) is a column value, or
** the SELECT statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN operator */
  int iTab,               /* Use this cursor number */
  int isRowid             /* If true, LHS is a rowid */
){
  int addrOnce = 0;           /* Address of the OP_Once instruction at top */
  int addr;                   /* Address of OP_OpenEphemeral instruction */
  Expr *pLeft;                /* the LHS of the IN operator */
  KeyInfo *pKeyInfo = 0;      /* Key information */
  int nVal;                   /* Size of vector pLeft */
  Vdbe *v;                    /* The prepared statement under construction */
................................................................................

    addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  }

  /* Check to see if this is a vector IN operator */
  pLeft = pExpr->pLeft;
  nVal = sqlite3ExprVectorSize(pLeft);
  assert( !isRowid || nVal==1 );

  /* Construct the ephemeral table that will contain the content of
  ** RHS of the IN operator.
  */
  pExpr->iTable = iTab;
  addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, 
      pExpr->iTable, (isRowid?0:nVal));
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
  }else{
    VdbeComment((v, "RHS of IN operator"));
  }
#endif
  pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, nVal, 1);

  if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    /* Case 1:     expr IN (SELECT ...)
    **
    ** Generate code to write the results of the select into the temporary
    ** table allocated and opened above.
    */
    Select *pSelect = pExpr->x.pSelect;
    ExprList *pEList = pSelect->pEList;

    ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY %d",
        addrOnce?"":"CORRELATED ", pSelect->selId
    ));
    assert( !isRowid );
    /* If the LHS and RHS of the IN operator do not match, that
    ** error will have been caught long before we reach this point. */
    if( ALWAYS(pEList->nExpr==nVal) ){
      SelectDest dest;
      int i;
      sqlite3SelectDestInit(&dest, SRT_Set, iTab);
      dest.zAffSdst = exprINAffinity(pParse, pExpr);
................................................................................
      assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
      pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
    }

    /* Loop through each expression in <exprlist>. */
    r1 = sqlite3GetTempReg(pParse);
    r2 = sqlite3GetTempReg(pParse);
    if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
    for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
      Expr *pE2 = pItem->pExpr;
      int iValToIns;

      /* If the expression is not constant then we will need to
      ** disable the test that was generated above that makes sure
      ** this code only executes once.  Because for a non-constant
      ** expression we need to rerun this code each time.
      */
      if( addrOnce && !sqlite3ExprIsConstant(pE2) ){
        sqlite3VdbeChangeToNoop(v, addrOnce);
        addrOnce = 0;
      }

      /* Evaluate the expression and insert it into the temp table */
      if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
        sqlite3VdbeAddOp3(v, OP_InsertInt, iTab, r2, iValToIns);
      }else{
        r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
        if( isRowid ){
          sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
                            sqlite3VdbeCurrentAddr(v)+2);
          VdbeCoverage(v);
          sqlite3VdbeAddOp3(v, OP_Insert, iTab, r2, r3);
        }else{
          sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
          sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
        }
      }
    }
    sqlite3ReleaseTempReg(pParse, r1);
    sqlite3ReleaseTempReg(pParse, r2);
  }
  if( pKeyInfo ){
    sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
  }
................................................................................
    pVTab = sqlite3GetVTable(db, pTab);
    if( pVTab->pVtab->pModule->xRename==0 ){
      pVTab = 0;
    }
  }
#endif

  /* Begin a transaction for database iDb. 
  ** Then modify the schema cookie (since the ALTER TABLE modifies the
  ** schema). Open a statement transaction if the table is a virtual
  ** table.
  */
  v = sqlite3GetVdbe(pParse);
  if( v==0 ){
    goto exit_rename_table;
  }


  /* figure out how many UTF-8 characters are in zName */
  zTabName = pTab->zName;
  nTabName = sqlite3Utf8CharLen(zTabName, -1);

  /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
  ** the schema to use the new table name.  */
................................................................................
  ** SQLite tables) that are identified by the name of the virtual table.
  */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  if( pVTab ){
    int i = ++pParse->nMem;
    sqlite3VdbeLoadString(v, i, zName);
    sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
    sqlite3MayAbort(pParse);
  }
#endif

  renameReloadSchema(pParse, iDb);
  renameTestSchema(pParse, zDb, iDb==1);

exit_rename_table:
................................................................................
    goto exit_rename_column;
  }

  /* Do the rename operation using a recursive UPDATE statement that
  ** uses the sqlite_rename_column() SQL function to compute the new
  ** CREATE statement text for the sqlite_master table.
  */

  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
................................................................................
  ** remove the entry from the db->aDb[] array. i.e. put everything back the
  ** way we found it.
  */
  if( rc==SQLITE_OK ){
    sqlite3BtreeEnterAll(db);
    db->init.iDb = 0;
    db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);

    rc = sqlite3Init(db, &zErrDyn);

    sqlite3BtreeLeaveAll(db);
    assert( zErrDyn==0 || rc!=SQLITE_OK );
  }
#ifdef SQLITE_USER_AUTHENTICATION
  if( rc==SQLITE_OK ){
    u8 newAuth = 0;
    rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
................................................................................

  if( pParse->nErr ) return;
  assert( pParse->nested<10 );  /* Nesting should only be of limited depth */
  va_start(ap, zFormat);
  zSql = sqlite3VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    return;   /* A malloc must have failed */




  }
  pParse->nested++;
  memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
  memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
  sqlite3RunParser(pParse, zSql, &zErrMsg);
  sqlite3DbFree(db, zErrMsg);
  sqlite3DbFree(db, zSql);
................................................................................
    sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
                       SQLITE_IDXTYPE_PRIMARYKEY);
    if( db->mallocFailed || pParse->nErr ) return;
    pPk = sqlite3PrimaryKeyIndex(pTab);
    pTab->iPKey = -1;
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);


    /*
    ** Remove all redundant columns from the PRIMARY KEY.  For example, change
    ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)".  Later
    ** code assumes the PRIMARY KEY contains no repeated columns.
    */
    for(i=j=1; i<pPk->nKeyCol; i++){
................................................................................
      sqlite3ErrorMsg(pParse, "");
      return;
    }
    p->tnum = db->init.newTnum;
    if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
  }






  /* Special processing for WITHOUT ROWID Tables */
  if( tabOpts & TF_WithoutRowid ){
    if( (p->tabFlags & TF_Autoincrement) ){
      sqlite3ErrorMsg(pParse,
          "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
      return;
    }
................................................................................
*/
static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
  FuncDef *pDef;
  pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
  if( ALWAYS(pDef) ){
    pDef->funcFlags |= flagVal;
  }




}

/*
** Register the built-in LIKE and GLOB functions.  The caseSensitive
** parameter determines whether or not the LIKE operator is case
** sensitive.  GLOB is always case sensitive.
*/
................................................................................
        sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
        VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
      }
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
    VdbeComment((v, "for %s", pIdx->zName));
#ifdef SQLITE_ENABLE_NULL_TRIM

    if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);

#endif

    /* In an UPDATE operation, if this index is the PRIMARY KEY index 
    ** of a WITHOUT ROWID table and there has been no change the
    ** primary key, then no collision is possible.  The collision detection
    ** logic below can all be skipped. */
    if( isUpdate && pPk==pIdx && pkChng==0 ){
................................................................................
    pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
      assert( pParse->nested==0 );
      pik_flags |= OPFLAG_NCHANGE;
      pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
      if( update_flags==0 ){


        sqlite3VdbeAddOp4(v, OP_InsertInt, 
            iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
        );
        sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);

      }
#endif
    }
    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
                         aRegIdx[i]+1,
                         pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
    sqlite3VdbeChangeP5(v, pik_flags);
................................................................................
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      sqlite3VdbeVerifyAbortable(v, onError);
      addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
      VdbeCoverage(v);
      sqlite3RowidConstraint(pParse, onError, pDest);
      sqlite3VdbeJumpHere(v, addr2);
      autoIncStep(pParse, regAutoinc, regRowid);
    }else if( pDest->pIndex==0 ){
      addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
    }else{
      addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
      assert( (pDest->tabFlags & TF_Autoincrement)==0 );
    }
    sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
    if( db->mDbFlags & DBFLAG_Vacuum ){
................................................................................
        if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
      }
      if( i==pSrcIdx->nColumn ){
        idxInsFlags = OPFLAG_USESEEKRESULT;
        sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
      }
    }
    if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
      idxInsFlags |= OPFLAG_NCHANGE;
    }
    sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
    sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
................................................................................

/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers i register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
................................................................................
    if( pIn ){
      int iMap = 0;               /* Index in aiMap[] */
      pIn += i;
      for(i=iEq;i<pLoop->nLTerm; i++){
        if( pLoop->aLTerm[i]->pExpr==pX ){
          int iOut = iReg + i - iEq;
          if( eType==IN_INDEX_ROWID ){
            testcase( nEq>1 );  /* Happens with a UNIQUE index on ROWID */
            pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
          }else{
            int iCol = aiMap ? aiMap[iMap++] : 0;
            pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
          }
          sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
          if( i==iEq ){
................................................................................
    x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
    sqlite3WalkExpr(&w, pWInfo->pWhere);
    sqlite3WalkExprList(&w, pWInfo->pOrderBy);
    sqlite3WalkExprList(&w, pWInfo->pResultSet);
  }
}





























/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
  Parse *pParse,       /* Parsing context */
  Vdbe *v,             /* Prepared statement under construction */
................................................................................
    iReleaseReg = ++pParse->nMem;
    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
    if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
    VdbeCoverage(v);
    pLevel->op = OP_Noop;



  }else if( (pLoop->wsFlags & WHERE_IPK)!=0
         && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
  ){
    /* Case 3:  We have an inequality comparison against the ROWID field.
    */
    int testOp = OP_Noop;
    int start;
................................................................................
    ** move forward to the next index.
    ** https://sqlite.org/src/info/4e8e4857d32d401f
    */
    if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
      whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
    }









    /* Record the instruction used to terminate the loop. */
    if( pLoop->wsFlags & WHERE_ONEROW ){
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
................................................................................
    assert( p->x.pList==0 );
  }else if( ExprHasProperty(p, EP_xIsSelect) ){
    if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
    mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
  }else if( p->x.pList ){
    mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
  }






  return mask;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
  return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
}
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
  int i;
................................................................................
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  sqlite3 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
  yyParser sEngine;    /* Space to hold the Lemon-generated Parser object */
#endif


  assert( zSql!=0 );
  mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
  if( db->nVdbeActive==0 ){
    db->u1.isInterrupted = 0;
  }
  pParse->rc = SQLITE_OK;
................................................................................
    return SQLITE_NOMEM_BKPT;
  }
#endif
  assert( pParse->pNewTable==0 );
  assert( pParse->pNewTrigger==0 );
  assert( pParse->nVar==0 );
  assert( pParse->pVList==0 );


  while( 1 ){
    n = sqlite3GetToken((u8*)zSql, &tokenType);
    mxSqlLen -= n;
    if( mxSqlLen<0 ){
      pParse->rc = SQLITE_TOOBIG;
      break;
    }
................................................................................
      }
    }
    pParse->sLastToken.z = zSql;
    pParse->sLastToken.n = n;
    sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
    lastTokenParsed = tokenType;
    zSql += n;

    if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
  }
  assert( nErr==0 );
#ifdef YYTRACKMAXSTACKDEPTH
  sqlite3_mutex_enter(sqlite3MallocMutex());
  sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
      sqlite3ParserStackPeak(pEngine)
  );
................................................................................
    sqlite3DbFreeNN(db, p);
  }
  while( pParse->pZombieTab ){
    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite3DeleteTable(db, p);
  }


  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
}


#ifdef SQLITE_ENABLE_NORMALIZE
/*
................................................................................
    if( !isFirstTerm ){
      zCsr += fts3GetVarint32(zCsr, &nPrefix);
    }
    isFirstTerm = 0;
    zCsr += fts3GetVarint32(zCsr, &nSuffix);
    
    assert( nPrefix>=0 && nSuffix>=0 );
    if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){
      rc = FTS_CORRUPT_VTAB;
      goto finish_scan;
    }
    if( (i64)nPrefix+nSuffix>nAlloc ){
      char *zNew;
      nAlloc = ((i64)nPrefix+nSuffix) * 2;
      zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc);
................................................................................
    if( !pPtr ){
      char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
      sqlite3_result_error(context, zErr, -1);
      sqlite3_free(zErr);
      return;
    }
  }

  sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);

}

SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){
  static const char isFtsIdChar[] = {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
................................................................................
      return SQLITE_OK;
    }

    fts3SegReaderSetEof(pReader);

    /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf 
    ** blocks have already been traversed.  */

    assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock );

    if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){
      return SQLITE_OK;
    }

    rc = sqlite3Fts3ReadBlock(
        p, ++pReader->iCurrentBlock, &pReader->aNode, &pReader->nNode, 
        (bIncr ? &pReader->nPopulate : 0)
................................................................................
    iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
    rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
    bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
  }
  if( rc!=SQLITE_OK ) goto finished;

  assert( csr.nSegment>0 );
  assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );

  assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );


  memset(&filter, 0, sizeof(Fts3SegFilter));
  filter.flags = FTS3_SEGMENT_REQUIRE_POS;
  filter.flags |= (bIgnoreEmpty ? FTS3_SEGMENT_IGNORE_EMPTY : 0);

  rc = sqlite3Fts3SegReaderStart(p, &csr, &filter);
  while( SQLITE_OK==rc ){
................................................................................

  for(i=0; i<pIter->nPhrase; i++){
    SnippetPhrase *pPhrase = &pIter->aPhrase[i];
    if( pPhrase->pTail ){
      char *pCsr = pPhrase->pTail;
      int iCsr = pPhrase->iTail;

      while( iCsr<(iStart+pIter->nSnippet) ){
        int j;
        u64 mPhrase = (u64)1 << i;
        u64 mPos = (u64)1 << (iCsr - iStart);
        assert( iCsr>=iStart && (iCsr - iStart)<=64 );
        assert( i>=0 && i<=64 );
        if( (mCover|mCovered)&mPhrase ){
          iScore++;
................................................................................
  int rc;

  UNUSED_PARAMETER(iPhrase);
  rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
  nTerm = pExpr->pPhrase->nToken;
  if( pList ){
    fts3GetDeltaPosition(&pList, &iPos);
    assert( iPos>=0 );
  }

  for(iTerm=0; iTerm<nTerm; iTerm++){
    TermOffset *pT = &p->aTerm[p->iTerm++];
    pT->iOff = nTerm-iTerm-1;
    pT->pList = pList;
    pT->iPos = iPos;
................................................................................
        }
      }

      if( !pTerm ){
        /* All offsets for this column have been gathered. */
        rc = SQLITE_DONE;
      }else{
        assert( iCurrent<=iMinPos );
        if( 0==(0xFE&*pTerm->pList) ){
          pTerm->pList = 0;
        }else{
          fts3GetDeltaPosition(&pTerm->pList, &pTerm->iPos);
        }
        while( rc==SQLITE_OK && iCurrent<iMinPos ){
          rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent);
................................................................................

  aOut = sqlite3_malloc(nOut+1);
  if( aOut==0 ){
    sqlite3_result_error_nomem(context);
  }else{
    nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut);
    if( nOut2!=nOut ){

      sqlite3_result_error(context, "corrupt fossil delta", -1);
    }else{
      sqlite3_result_blob(context, aOut, nOut, sqlite3_free);
    }
  }
}

................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   of the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function, an
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**
................................................................................
            /* Set the szLeaf field */
            fts5PutU16(&buf.p[2], (u16)buf.n);
          }

          /* Set up the new page-index array */
          fts5BufferAppendVarint(&p->rc, &buf, 4);
          if( pSeg->iLeafPgno==pSeg->iTermLeafPgno 
              && pSeg->iEndofDoclist<pData->szLeaf 

            ){
            int nDiff = pData->szLeaf - pSeg->iEndofDoclist;
            fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4);
            fts5BufferAppendBlob(&p->rc, &buf, 
                pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff]
                );
          }

          pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
          fts5DataDelete(p, FTS5_SEGMENT_ROWID(iId, 1), iLeafRowid);
          fts5DataWrite(p, iLeafRowid, buf.p, buf.n);
        }
        fts5DataRelease(pData);
................................................................................
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd", -1, SQLITE_TRANSIENT);
}

/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
................................................................................
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=221843
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/

Changes to src/sqlite3.h.

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
....
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
....
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
....
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
....
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
....
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
.....
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
.....
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.28.0"
#define SQLITE_VERSION_NUMBER 3028000
#define SQLITE_SOURCE_ID      "2019-03-17 23:59:02 cc5ab96715ebb1089b4e9aa647badd2510aaa056f26004718f921f4ac07e2f93"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the
** [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
................................................................................
** does not affect the value returned by sqlite3_total_changes().
** 
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers 
** are not counted.
**
** The [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D.  Any changes by other database connections are ignored.
** To detect changes against a database file from other database
** connections use the [PRAGMA data_version] command or the
** [SQLITE_FCNTL_DATA_VERSION] [file control].
** 
** If a separate thread makes changes on the same database connection
................................................................................
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
** prepared statement S is an EXPLAIN statement, or 2 if the
** statement S is an EXPLAIN QUERY PLAN.
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
** an ordinary statement or a NULL pointer.
*/
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite3_step(S)] but has neither run to completion (returned
................................................................................
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to the bind API fails,
** except the destructor is not called if the third parameter is a NULL
** pointer or the fourth parameter is negative.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
................................................................................
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** this function will return either a NULL pointer or an empty string.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function,
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**







|
|
|







 







|
|







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<







 







|
<
<







 







|







 







|







 







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
....
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
....
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
....
3890
3891
3892
3893
3894
3895
3896












3897
3898
3899
3900
3901
3902
3903
....
4029
4030
4031
4032
4033
4034
4035
4036


4037
4038
4039
4040
4041
4042
4043
....
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
.....
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
.....
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.27.1"
#define SQLITE_VERSION_NUMBER 3027001
#define SQLITE_SOURCE_ID      "2019-02-08 13:17:39 0eca3dd3d38b31c92b49ca2d311128b74584714d9e7de895b1a6286ef959a1dd"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
** [FTS3] full-text search engine extension.
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
** positive to enable fts3_tokenizer() or negative to leave the setting
** unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
................................................................................
** does not affect the value returned by sqlite3_total_changes().
** 
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers 
** are not counted.
**
** This the [sqlite3_total_changes(D)] interface only reports the number
** of rows that changed due to SQL statement run against database
** connection D.  Any changes by other database connections are ignored.
** To detect changes against a database file from other database
** connections use the [PRAGMA data_version] command or the
** [SQLITE_FCNTL_DATA_VERSION] [file control].
** 
** If a separate thread makes changes on the same database connection
................................................................................
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);













/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite3_step(S)] but has neither run to completion (returned
................................................................................
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to bind API fails.


** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.
**
................................................................................
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** a NULL pointer is returned.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
................................................................................
**
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
**   Save the pointer passed as the second argument as the extension functions 
**   "auxiliary data". The pointer may then be retrieved by the current or any
**   future invocation of the same fts5 extension function made as part of
**   of the same MATCH query using the xGetAuxdata() API.
**
**   Each extension function is allocated a single auxiliary data slot for
**   each FTS query (MATCH expression). If the extension function is invoked 
**   more than once for a single FTS query, then all invocations share a 
**   single auxiliary data context.
**
**   If there is already an auxiliary data pointer when this function is
................................................................................
**   invoked, then it is replaced by the new pointer. If an xDelete callback
**   was specified along with the original pointer, it is invoked at this
**   point.
**
**   The xDelete callback, if one is specified, is also invoked on the
**   auxiliary data pointer after the FTS5 query has finished.
**
**   If an error (e.g. an OOM condition) occurs within this function, an
**   the auxiliary data is set to NULL and an error code returned. If the
**   xDelete parameter was not NULL, it is invoked on the auxiliary data
**   pointer before returning.
**
**
** xGetAuxdata(pFts5, bClear)
**

Changes to src/stash.c.

534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
**     Show the contents of a stash as a diff against its baseline.
**     With gshow and gcat, gdiff-command is used instead of internal
**     diff logic.
**
**  fossil stash pop
**  fossil stash apply ?STASHID?
**
**     Apply STASHID or the most recently created stash to the current
**     working checkout.  The "pop" command deletes that changeset from
**     the stash after applying it but the "apply" command retains the
**     changeset.
**
**  fossil stash goto ?STASHID?
**
**     Update to the baseline checkout for STASHID then apply the
................................................................................
      db_finalize(&q);
      newArgv[0] = g.argv[0];
      newArgv[1] = 0;
      g.argv = newArgv;
      g.argc = nFile+2;
      if( nFile==0 ) return;
    }
    /* Make sure the stash has committed before running the revert, so that
    ** we have a copy of the changes before deleting them. */
    db_commit_transaction();
    g.argv[1] = "revert";
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){







|







 







<
<
<







534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
...
606
607
608
609
610
611
612



613
614
615
616
617
618
619
**     Show the contents of a stash as a diff against its baseline.
**     With gshow and gcat, gdiff-command is used instead of internal
**     diff logic.
**
**  fossil stash pop
**  fossil stash apply ?STASHID?
**
**     Apply STASHID or the most recently create stash to the current
**     working checkout.  The "pop" command deletes that changeset from
**     the stash after applying it but the "apply" command retains the
**     changeset.
**
**  fossil stash goto ?STASHID?
**
**     Update to the baseline checkout for STASHID then apply the
................................................................................
      db_finalize(&q);
      newArgv[0] = g.argv[0];
      newArgv[1] = 0;
      g.argv = newArgv;
      g.argc = nFile+2;
      if( nFile==0 ) return;
    }



    g.argv[1] = "revert";
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){

Changes to src/sync.c.

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  }
  if( find_option("verbose","v",0)!=0 ){
    *pSyncFlags |= SYNC_VERBOSE;
  }
  url_proxy_options();
  clone_ssh_find_options();
  if( !uvOnly ) db_find_and_open_repository(0, 0);
  db_open_config(0, 1);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
   && db_get_boolean("uv-sync",0)







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  }
  if( find_option("verbose","v",0)!=0 ){
    *pSyncFlags |= SYNC_VERBOSE;
  }
  url_proxy_options();
  clone_ssh_find_options();
  if( !uvOnly ) db_find_and_open_repository(0, 0);
  db_open_config(0, 0);
  if( g.argc==2 ){
    if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
  }else if( g.argc==3 ){
    zUrl = g.argv[2];
  }
  if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL)
   && db_get_boolean("uv-sync",0)

Changes to src/th_tcl.c.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
#      define _WIN32_WINNT 0x0502 /* SetDllDirectory, Windows XP SP2 */
#    endif
#    include <windows.h>
#    ifndef TCL_DIRECTORY_SEP
#      define TCL_DIRECTORY_SEP '\\'
#    endif
#    ifndef TCL_LIBRARY_NAME
#      define TCL_LIBRARY_NAME "tcl87.dll\0"
#    endif
#    ifndef TCL_MINOR_OFFSET
#      define TCL_MINOR_OFFSET (4)
#    endif
#    ifndef dlopen
#      define dlopen(a,b) (void *)LoadLibrary((a))
#    endif
................................................................................
#  else
#    include <dlfcn.h>
#    ifndef TCL_DIRECTORY_SEP
#      define TCL_DIRECTORY_SEP '/'
#    endif
#    if defined(__CYGWIN__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.7.dll\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    elif defined(__APPLE__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.7.dylib\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    elif defined(__FreeBSD__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl87.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (7)
#      endif
#    else
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.7.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    endif /* defined(__CYGWIN__) */
#  endif /* defined(_WIN32) */
#  ifndef TCL_FINDEXECUTABLE_NAME
................................................................................
      *pxDeleteInterp = xDeleteInterp;
      *pxFinalize = xFinalize;
      return TH_OK;
    }
  } while( --aFileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
  aFileName[TCL_MINOR_OFFSET] = 'x';
  Th_ErrorMessage(interp,
      "could not load any supported Tcl 8.x shared library \"",
      aFileName, -1);
  return TH_ERROR;
#else
  *phLibrary = 0;
  *pxFindExecutable = Tcl_FindExecutable;
  *pxCreateInterp = Tcl_CreateInterp;
  *pxDeleteInterp = Tcl_DeleteInterp;
................................................................................
  Tcl_IncrRefCount(objPtr);
  resultObjPtr = Tcl_SetVar2Ex(pInterp, "argv0", NULL, objPtr,
      TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
  Tcl_DecrRefCount(objPtr); objPtr = 0;
  if( !resultObjPtr ){
    return TCL_ERROR;
  }
  objPtr = Tcl_NewWideIntObj(argc - 1);
  Tcl_IncrRefCount(objPtr);
  resultObjPtr = Tcl_SetVar2Ex(pInterp, "argc", NULL, objPtr,
      TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
  Tcl_DecrRefCount(objPtr); objPtr = 0;
  if( !resultObjPtr ){
    return TCL_ERROR;
  }
................................................................................
  tclContext->useTip285 = canUseTip285();
  /* Add the TH1 integration commands to Tcl. */
  Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp);
  Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL);
  Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL);
  /* If necessary, evaluate the custom Tcl setup script. */
  setup = tclContext->setup;
  if( setup && Tcl_EvalEx(tclInterp, setup, -1, 0)!=TCL_OK ){
    Th_ErrorMessage(interp,
        "Tcl setup script error:", Tcl_GetStringResult(tclInterp), -1);
    Tcl_DeleteInterp(tclInterp);
    tclContext->interp = tclInterp = 0;
    return TH_ERROR;
  }
  return TH_OK;







|







 







|






|






|






|







 







|







 







|







 







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
#      define _WIN32_WINNT 0x0502 /* SetDllDirectory, Windows XP SP2 */
#    endif
#    include <windows.h>
#    ifndef TCL_DIRECTORY_SEP
#      define TCL_DIRECTORY_SEP '\\'
#    endif
#    ifndef TCL_LIBRARY_NAME
#      define TCL_LIBRARY_NAME "tcl86.dll\0"
#    endif
#    ifndef TCL_MINOR_OFFSET
#      define TCL_MINOR_OFFSET (4)
#    endif
#    ifndef dlopen
#      define dlopen(a,b) (void *)LoadLibrary((a))
#    endif
................................................................................
#  else
#    include <dlfcn.h>
#    ifndef TCL_DIRECTORY_SEP
#      define TCL_DIRECTORY_SEP '/'
#    endif
#    if defined(__CYGWIN__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.dll\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    elif defined(__APPLE__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.dylib\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    elif defined(__FreeBSD__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl86.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (7)
#      endif
#    else
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    endif /* defined(__CYGWIN__) */
#  endif /* defined(_WIN32) */
#  ifndef TCL_FINDEXECUTABLE_NAME
................................................................................
      *pxDeleteInterp = xDeleteInterp;
      *pxFinalize = xFinalize;
      return TH_OK;
    }
  } while( --aFileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
  aFileName[TCL_MINOR_OFFSET] = 'x';
  Th_ErrorMessage(interp,
      "could not load any supported Tcl 8.6, 8.5, or 8.4 shared library \"",
      aFileName, -1);
  return TH_ERROR;
#else
  *phLibrary = 0;
  *pxFindExecutable = Tcl_FindExecutable;
  *pxCreateInterp = Tcl_CreateInterp;
  *pxDeleteInterp = Tcl_DeleteInterp;
................................................................................
  Tcl_IncrRefCount(objPtr);
  resultObjPtr = Tcl_SetVar2Ex(pInterp, "argv0", NULL, objPtr,
      TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
  Tcl_DecrRefCount(objPtr); objPtr = 0;
  if( !resultObjPtr ){
    return TCL_ERROR;
  }
  objPtr = Tcl_NewIntObj(argc - 1);
  Tcl_IncrRefCount(objPtr);
  resultObjPtr = Tcl_SetVar2Ex(pInterp, "argc", NULL, objPtr,
      TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
  Tcl_DecrRefCount(objPtr); objPtr = 0;
  if( !resultObjPtr ){
    return TCL_ERROR;
  }
................................................................................
  tclContext->useTip285 = canUseTip285();
  /* Add the TH1 integration commands to Tcl. */
  Tcl_CallWhenDeleted(tclInterp, Th1DeleteProc, interp);
  Tcl_CreateObjCommand(tclInterp, "th1Eval", Th1EvalObjCmd, interp, NULL);
  Tcl_CreateObjCommand(tclInterp, "th1Expr", Th1ExprObjCmd, interp, NULL);
  /* If necessary, evaluate the custom Tcl setup script. */
  setup = tclContext->setup;
  if( setup && Tcl_Eval(tclInterp, setup)!=TCL_OK ){
    Th_ErrorMessage(interp,
        "Tcl setup script error:", Tcl_GetStringResult(tclInterp), -1);
    Tcl_DeleteInterp(tclInterp);
    tclContext->interp = tclInterp = 0;
    return TH_ERROR;
  }
  return TH_OK;

Changes to src/unicode.c.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

146
147
148
149
150
151
152
153
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202
203
204




205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
    0x0027E802, 0x0027F402, 0x00280403, 0x0028F001, 0x0028F805,
    0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D402,
    0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
    0x002B8802, 0x002BC002, 0x002BE806, 0x002C0403, 0x002CF001,
    0x002CF807, 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802,
    0x002DC001, 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804,
    0x002F5C01, 0x002FCC08, 0x00300005, 0x0030F807, 0x00311803,
    0x00312804, 0x00315402, 0x00318802, 0x0031DC01, 0x0031FC01,
    0x00320404, 0x0032F001, 0x0032F807, 0x00331803, 0x00332804,
    0x00335402, 0x00338802, 0x00340004, 0x0034EC02, 0x0034F807,
    0x00351803, 0x00352804, 0x00353C01, 0x00355C01, 0x00358802,
    0x0035E401, 0x00360802, 0x00372801, 0x00373C06, 0x00375801,
    0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, 0x0038FC01,
    0x00391C09, 0x00396802, 0x003AC401, 0x003AD009, 0x003B2006,
    0x003C041F, 0x003CD00C, 0x003DC417, 0x003E340B, 0x003E6424,
    0x003EF80F, 0x003F380D, 0x0040AC14, 0x00412806, 0x00415804,
    0x00417803, 0x00418803, 0x00419C07, 0x0041C404, 0x0042080C,
    0x00423C01, 0x00426806, 0x0043EC01, 0x004D740C, 0x004E400A,
    0x00500001, 0x0059B402, 0x005A0001, 0x005A6C02, 0x005BAC03,
    0x005C4803, 0x005CC805, 0x005D4802, 0x005DC802, 0x005ED023,
    0x005F6004, 0x005F7401, 0x0060000F, 0x00621402, 0x0062A401,
    0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, 0x00677822,
    0x00685C05, 0x00687802, 0x0069540A, 0x0069801D, 0x0069FC01,
    0x006A8007, 0x006AA006, 0x006AC00F, 0x006C0005, 0x006CD011,
    0x006D6823, 0x006E0003, 0x006E840D, 0x006F980E, 0x006FF004,
    0x00709014, 0x0070EC05, 0x0071F802, 0x00730008, 0x00734019,
    0x0073B401, 0x0073D001, 0x0073DC03, 0x0077003A, 0x0077EC05,
    0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, 0x007FB403,
    0x007FF402, 0x00800065, 0x0081980A, 0x0081E805, 0x00822805,
    0x00828020, 0x00834021, 0x00840002, 0x00840C04, 0x00842002,
    0x00845001, 0x00845803, 0x00847806, 0x00849401, 0x00849C01,
    0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, 0x00852804,
    0x00853C01, 0x00862802, 0x00864297, 0x0091000B, 0x0092704E,
    0x00940276, 0x009E53E0, 0x00ADD820, 0x00AE6068, 0x00B39406,
    0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, 0x00B5FC01,
    0x00B7804F, 0x00B8C020, 0x00BA001A, 0x00BA6C59, 0x00BC00D6,
    0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, 0x00C0D802,
    0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, 0x00C64002,
    0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, 0x00C94001,
    0x00C98020, 0x00CA2827, 0x00CB0140, 0x01370040, 0x02924037,
    0x0293F802, 0x02983403, 0x0299BC10, 0x029A7802, 0x029BC008,
    0x029C0017, 0x029C8002, 0x029E2402, 0x02A00801, 0x02A01801,
    0x02A02C01, 0x02A08C09, 0x02A0D804, 0x02A1D004, 0x02A20002,
    0x02A2D012, 0x02A33802, 0x02A38012, 0x02A3E003, 0x02A3F001,
    0x02A3FC01, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
    0x02A6CC1B, 0x02A77802, 0x02A79401, 0x02A8A40E, 0x02A90C01,
    0x02A93002, 0x02A97004, 0x02A9DC03, 0x02A9EC03, 0x02AAC001,
    0x02AAC803, 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802,
    0x02ABAC07, 0x02ABD402, 0x02AD6C01, 0x02AF8C0B, 0x03600001,
    0x036DFC02, 0x036FFC02, 0x037FFC01, 0x03EC7801, 0x03ECA401,
    0x03EEC810, 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88033,
    0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
    0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
    0x04040003, 0x0404DC09, 0x0405E411, 0x04063003, 0x0406400C,
    0x04068001, 0x0407402E, 0x040B8001, 0x040DD805, 0x040E7C01,
    0x040F4001, 0x0415BC01, 0x04215C01, 0x0421DC02, 0x04247C01,
    0x0424FC01, 0x04280403, 0x04281402, 0x04283004, 0x0428E003,
    0x0428FC01, 0x04294009, 0x0429FC01, 0x042B2001, 0x042B9402,
    0x042BC007, 0x042CE407, 0x042E6404, 0x04349004, 0x043D180B,
    0x043D5405, 0x04400003, 0x0440E016, 0x0441FC04, 0x0442C012,
    0x04433401, 0x04440003, 0x04449C0E, 0x04450004, 0x04451402,
    0x0445CC03, 0x04460003, 0x0446CC0E, 0x04471409, 0x04476C01,
    0x04477403, 0x0448B013, 0x044AA401, 0x044B7C0C, 0x044C0004,
    0x044CEC02, 0x044CF807, 0x044D1C02, 0x044D2C03, 0x044D5C01,
    0x044D8802, 0x044D9807, 0x044DC005, 0x0450D412, 0x04512C05,
    0x04516C01, 0x04517402, 0x0452C014, 0x04531801, 0x0456BC07,
    0x0456E020, 0x04577002, 0x0458C014, 0x0459800D, 0x045AAC0D,
    0x045C740F, 0x045CF004, 0x0460B010, 0x04674407, 0x04676807,
    0x04678801, 0x04679001, 0x0468040A, 0x0468CC07, 0x0468EC0D,
    0x0469440B, 0x046A2813, 0x046A7805, 0x0470BC08, 0x0470E008,
    0x04710405, 0x0471C002, 0x04724816, 0x0472A40E, 0x0474C406,
    0x0474E801, 0x0474F002, 0x0474FC07, 0x04751C01, 0x04762805,
    0x04764002, 0x04764C05, 0x047BCC06, 0x047F541D, 0x047FFC01,
    0x0491C005, 0x04D0C009, 0x05A9B802, 0x05ABC006, 0x05ACC010,
    0x05AD1002, 0x05BA5C04, 0x05BD3C01, 0x05BD4437, 0x05BE3C04,
    0x05BF8801, 0x06F27008, 0x074000F6, 0x07440027, 0x0744A4C0,
    0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
    0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
    0x075EA401, 0x075F0C01, 0x0760028C, 0x076A6C05, 0x076A840F,
    0x07800007, 0x07802011, 0x07806C07, 0x07808C02, 0x07809805,
    0x0784C007, 0x07853C01, 0x078BB004, 0x078BFC01, 0x07A34007,
    0x07A51007, 0x07A57802, 0x07B2B001, 0x07B2C001, 0x07B4B801,
    0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F, 0x07C2C40F,
    0x07C3040F, 0x07C34425, 0x07C4405D, 0x07C5C03D, 0x07C7981D,
    0x07C8402C, 0x07C90009, 0x07C94002, 0x07C98006, 0x07CC03D6,
    0x07DB800D, 0x07DBC00B, 0x07DC0074, 0x07DE0059, 0x07DF800C,
    0x07E0000C, 0x07E04038, 0x07E1400A, 0x07E18028, 0x07E2401E,
    0x07E4000C, 0x07E43465, 0x07E5CC04, 0x07E5E829, 0x07E69406,
    0x07E6B81D, 0x07E73487, 0x07E9800E, 0x07E9C004, 0x07E9E003,

    0x07EA0003, 0x07EA4006, 0x38000401, 0x38008060, 0x380400F0,
  };
  static const unsigned int aAscii[4] = {
    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
  };

  if( (unsigned int)c<128 ){
    return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
................................................................................
** If the argument is a codepoint corresponding to a lowercase letter
** in the ASCII range with a diacritic added, return the codepoint
** of the ASCII letter only. For example, if passed 235 - "LATIN
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int unicode_remove_diacritic(int c, int bComplex){
  static const unsigned short aDia[] = {
        0,  1797,  1848,  1859,  1891,  1928,  1940,  1995,
     2024,  2040,  2060,  2110,  2168,  2206,  2264,  2286,
     2344,  2383,  2472,  2488,  2516,  2596,  2668,  2732,
     2782,  2842,  2894,  2954,  2984,  3000,  3028,  3336,
     3456,  3696,  3712,  3728,  3744,  3766,  3832,  3896,
     3912,  3928,  3944,  3968,  4008,  4040,  4056,  4106,
     4138,  4170,  4202,  4234,  4266,  4296,  4312,  4344,
     4408,  4424,  4442,  4472,  4488,  4504,  6148,  6198,
     6264,  6280,  6360,  6429,  6505,  6529, 61448, 61468,

    61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
    61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
    61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
    62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
    62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
    62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
    63182, 63242, 63274, 63310, 63368, 63390,
  };
#define HIBIT ((unsigned char)0x80)
  static const unsigned char aChar[] = {




    '\0',      'a',       'c',       'e',       'i',       'n',
    'o',       'u',       'y',       'y',       'a',       'c',
    'd',       'e',       'e',       'g',       'h',       'i',
    'j',       'k',       'l',       'n',       'o',       'r',
    's',       't',       'u',       'u',       'w',       'y',
    'z',       'o',       'u',       'a',       'i',       'o',
    'u',       'u'|HIBIT, 'a'|HIBIT, 'g',       'k',       'o',
    'o'|HIBIT, 'j',       'g',       'n',       'a'|HIBIT, 'a',
    'e',       'i',       'o',       'r',       'u',       's',
    't',       'h',       'a',       'e',       'o'|HIBIT, 'o',
    'o'|HIBIT, 'y',       '\0',      '\0',      '\0',      '\0',
    '\0',      '\0',      '\0',      '\0',      'a',       'b',
    'c'|HIBIT, 'd',       'd',       'e'|HIBIT, 'e',       'e'|HIBIT,
    'f',       'g',       'h',       'h',       'i',       'i'|HIBIT,
    'k',       'l',       'l'|HIBIT, 'l',       'm',       'n',
    'o'|HIBIT, 'p',       'r',       'r'|HIBIT, 'r',       's',
    's'|HIBIT, 't',       'u',       'u'|HIBIT, 'v',       'w',
    'w',       'x',       'y',       'z',       'h',       't',
    'w',       'y',       'a',       'a'|HIBIT, 'a'|HIBIT, 'a'|HIBIT,
    'e',       'e'|HIBIT, 'e'|HIBIT, 'i',       'o',       'o'|HIBIT,
    'o'|HIBIT, 'o'|HIBIT, 'u',       'u'|HIBIT, 'u'|HIBIT, 'y',
  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
................................................................................
      iRes = iTest;
      iLo = iTest+1;
    }else{
      iHi = iTest-1;
    }
  }
  assert( key>=aDia[iRes] );
  if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
  return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}


/*
** Return true if the argument interpreted as a unicode codepoint
** is a diacritical modifier character.
*/
int unicode_is_diacritic(int c){
  unsigned int mask0 = 0x08029FDF;
  unsigned int mask1 = 0x000361F8;
  if( c<768 || c>817 ) return 0;
  return (c < 768+32) ?
      (mask0 & ((unsigned int)1 << (c-768))) :
      (mask1 & ((unsigned int)1 << (c-768-32)));
}


/*
** Interpret the argument as a unicode codepoint. If the codepoint
** is an upper case character that has a lower case equivalent,
** return the codepoint corresponding to the lower case version.
** Otherwise, return a copy of the argument.
**
** The results are undefined if the value passed to this function
** is less than zero.
*/
int unicode_fold(int c, int eRemoveDiacritic){
  /* Each entry in the following array defines a rule for folding a range
  ** of codepoints to lower case. The rule applies to a range of nRange
  ** codepoints starting at codepoint iCode.
  **
  ** If the least significant bit in flags is clear, then the rule applies
  ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
  ** need to be folded). Or, if it is set, then the rule only applies to
................................................................................
  static const struct TableEntry {
    unsigned short iCode;
    unsigned char flags;
    unsigned char nRange;
  } aEntry[] = {
    {65, 14, 26},          {181, 66, 1},          {192, 14, 23},
    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
    {313, 1, 16},          {330, 1, 46},          {376, 156, 1},
    {377, 1, 6},           {383, 144, 1},         {385, 52, 1},
    {386, 1, 4},           {390, 46, 1},          {391, 0, 1},
    {393, 44, 2},          {395, 0, 1},           {398, 34, 1},
    {399, 40, 1},          {400, 42, 1},          {401, 0, 1},
    {403, 44, 1},          {404, 48, 1},          {406, 54, 1},
    {407, 50, 1},          {408, 0, 1},           {412, 54, 1},
    {413, 56, 1},          {415, 58, 1},          {416, 1, 6},
    {422, 62, 1},          {423, 0, 1},           {425, 62, 1},
    {428, 0, 1},           {430, 62, 1},          {431, 0, 1},
    {433, 60, 2},          {435, 1, 4},           {439, 64, 1},
    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
    {497, 2, 1},           {498, 1, 4},           {502, 162, 1},
    {503, 174, 1},         {504, 1, 40},          {544, 150, 1},
    {546, 1, 18},          {570, 74, 1},          {571, 0, 1},
    {573, 148, 1},         {574, 72, 1},          {577, 0, 1},
    {579, 146, 1},         {580, 30, 1},          {581, 32, 1},
    {582, 1, 10},          {837, 38, 1},          {880, 1, 4},
    {886, 0, 1},           {895, 38, 1},          {902, 20, 1},
    {904, 18, 3},          {908, 28, 1},          {910, 26, 2},
    {913, 14, 17},         {931, 14, 9},          {962, 0, 1},
    {975, 4, 1},           {976, 180, 1},         {977, 182, 1},
    {981, 186, 1},         {982, 184, 1},         {984, 1, 24},
    {1008, 176, 1},        {1009, 178, 1},        {1012, 170, 1},
    {1013, 168, 1},        {1015, 0, 1},          {1017, 192, 1},
    {1018, 0, 1},          {1021, 150, 3},        {1024, 36, 16},
    {1040, 14, 32},        {1120, 1, 34},         {1162, 1, 54},
    {1216, 6, 1},          {1217, 1, 14},         {1232, 1, 96},
    {1329, 24, 38},        {4256, 70, 38},        {4295, 70, 1},
    {4301, 70, 1},         {5112, 190, 6},        {7296, 126, 1},
    {7297, 128, 1},        {7298, 130, 1},        {7299, 134, 2},
    {7301, 132, 1},        {7302, 136, 1},        {7303, 138, 1},
    {7304, 100, 1},        {7312, 142, 43},       {7357, 142, 3},
    {7680, 1, 150},        {7835, 172, 1},        {7838, 120, 1},
    {7840, 1, 96},         {7944, 190, 8},        {7960, 190, 6},
    {7976, 190, 8},        {7992, 190, 8},        {8008, 190, 6},
    {8025, 191, 8},        {8040, 190, 8},        {8072, 190, 8},
    {8088, 190, 8},        {8104, 190, 8},        {8120, 190, 2},
    {8122, 166, 2},        {8124, 188, 1},        {8126, 124, 1},
    {8136, 164, 4},        {8140, 188, 1},        {8152, 190, 2},
    {8154, 160, 2},        {8168, 190, 2},        {8170, 158, 2},
    {8172, 192, 1},        {8184, 152, 2},        {8186, 154, 2},
    {8188, 188, 1},        {8486, 122, 1},        {8490, 116, 1},
    {8491, 118, 1},        {8498, 12, 1},         {8544, 8, 16},
    {8579, 0, 1},          {9398, 10, 26},        {11264, 24, 47},
    {11360, 0, 1},         {11362, 112, 1},       {11363, 140, 1},
    {11364, 114, 1},       {11367, 1, 6},         {11373, 108, 1},
    {11374, 110, 1},       {11375, 104, 1},       {11376, 106, 1},
    {11378, 0, 1},         {11381, 0, 1},         {11390, 102, 2},
    {11392, 1, 100},       {11499, 1, 4},         {11506, 0, 1},
    {42560, 1, 46},        {42624, 1, 28},        {42786, 1, 14},
    {42802, 1, 62},        {42873, 1, 4},         {42877, 98, 1},
    {42878, 1, 10},        {42891, 0, 1},         {42893, 88, 1},
    {42896, 1, 4},         {42902, 1, 20},        {42922, 80, 1},
    {42923, 76, 1},        {42924, 78, 1},        {42925, 84, 1},
    {42926, 80, 1},        {42928, 92, 1},        {42929, 86, 1},
    {42930, 90, 1},        {42931, 68, 1},        {42932, 1, 12},
    {42946, 0, 1},         {42948, 178, 1},       {42949, 82, 1},
    {42950, 96, 1},        {43888, 94, 80},       {65313, 14, 26},
  };
  static const unsigned short aiOff[] = {
   1,     2,     8,     15,    16,    26,    28,    32,
   34,    37,    38,    40,    48,    63,    64,    69,
   71,    79,    80,    116,   202,   203,   205,   206,
   207,   209,   210,   211,   213,   214,   217,   218,
   219,   775,   928,   7264,  10792, 10795, 23217, 23221,
   23228, 23229, 23231, 23254, 23256, 23275, 23278, 26672,
   30152, 30204, 35267, 54721, 54753, 54754, 54756, 54787,
   54793, 54809, 57153, 57274, 57921, 58019, 58363, 59314,
   59315, 59324, 59325, 59326, 59332, 59356, 61722, 62528,
   65268, 65341, 65373, 65406, 65408, 65410, 65415, 65424,
   65436, 65439, 65450, 65462, 65472, 65476, 65478, 65480,
   65482, 65488, 65506, 65511, 65514, 65521, 65527, 65528,
   65529,
  };

  int ret = c;

  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );

  if( c<128 ){
................................................................................
    assert( iRes>=0 && c>=aEntry[iRes].iCode );
    p = &aEntry[iRes];
    if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
      ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
      assert( ret>0 );
    }

    if( eRemoveDiacritic ){
      ret = unicode_remove_diacritic(ret, eRemoveDiacritic==2);
    }
  }

  else if( c>=66560 && c<66600 ){
    ret = c + 40;
  }
  else if( c>=66736 && c<66772 ){
    ret = c + 40;







|
|
|
|
|
|
|












|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
<
|
|
|
|
|
|
<
<
>
|







 







|





|
|
|
<
|
>
|
|
<
<
|
|
<

<
|
>
>
>
>
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
|












|
|












|







 







|
|












|
|

|
|




|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|


|
|

|
|
|
<
|







|
|
|
|
|
|
|
<







 







<
|
<







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135

136
137
138
139
140
141


142
143
144
145
146
147
148
149
150
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193


194
195

196

197
198
199
200
201
202
203
204
205
206
















207
208
209
210
211
212
213
...
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

334
335
336
337
338
339
340
341
342
343
344
345
346
347
348

349
350
351
352
353
354
355
...
375
376
377
378
379
380
381

382

383
384
385
386
387
388
389
    0x0027E802, 0x0027F402, 0x00280403, 0x0028F001, 0x0028F805,
    0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D402,
    0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
    0x002B8802, 0x002BC002, 0x002BE806, 0x002C0403, 0x002CF001,
    0x002CF807, 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802,
    0x002DC001, 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804,
    0x002F5C01, 0x002FCC08, 0x00300005, 0x0030F807, 0x00311803,
    0x00312804, 0x00315402, 0x00318802, 0x0031FC01, 0x00320404,
    0x0032F001, 0x0032F807, 0x00331803, 0x00332804, 0x00335402,
    0x00338802, 0x00340004, 0x0034EC02, 0x0034F807, 0x00351803,
    0x00352804, 0x00353C01, 0x00355C01, 0x00358802, 0x0035E401,
    0x00360802, 0x00372801, 0x00373C06, 0x00375801, 0x00376008,
    0x0037C803, 0x0038C401, 0x0038D007, 0x0038FC01, 0x00391C09,
    0x00396802, 0x003AC401, 0x003AD006, 0x003AEC02, 0x003B2006,
    0x003C041F, 0x003CD00C, 0x003DC417, 0x003E340B, 0x003E6424,
    0x003EF80F, 0x003F380D, 0x0040AC14, 0x00412806, 0x00415804,
    0x00417803, 0x00418803, 0x00419C07, 0x0041C404, 0x0042080C,
    0x00423C01, 0x00426806, 0x0043EC01, 0x004D740C, 0x004E400A,
    0x00500001, 0x0059B402, 0x005A0001, 0x005A6C02, 0x005BAC03,
    0x005C4803, 0x005CC805, 0x005D4802, 0x005DC802, 0x005ED023,
    0x005F6004, 0x005F7401, 0x0060000F, 0x00621402, 0x0062A401,
    0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, 0x00677822,
    0x00685C05, 0x00687802, 0x0069540A, 0x0069801D, 0x0069FC01,
    0x006A8007, 0x006AA006, 0x006AC00F, 0x006C0005, 0x006CD011,
    0x006D6823, 0x006E0003, 0x006E840D, 0x006F980E, 0x006FF004,
    0x00709014, 0x0070EC05, 0x0071F802, 0x00730008, 0x00734019,
    0x0073B401, 0x0073C803, 0x0073DC03, 0x0077003A, 0x0077EC05,
    0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, 0x007FB403,
    0x007FF402, 0x00800065, 0x0081980A, 0x0081E805, 0x00822805,
    0x00828020, 0x00834021, 0x00840002, 0x00840C04, 0x00842002,
    0x00845001, 0x00845803, 0x00847806, 0x00849401, 0x00849C01,
    0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, 0x00852804,
    0x00853C01, 0x00862802, 0x00864297, 0x0091000B, 0x0092704E,
    0x00940276, 0x009E53E0, 0x00ADD820, 0x00AE6031, 0x00AF2835,
    0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
    0x00B5FC01, 0x00B7804F, 0x00B8C01F, 0x00BA001A, 0x00BA6C59,
    0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
    0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
    0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
    0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
    0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
    0x029A7802, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
    0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
    0x02A1D004, 0x02A20002, 0x02A2D012, 0x02A33802, 0x02A38012,
    0x02A3E003, 0x02A3F001, 0x02A3FC01, 0x02A4980A, 0x02A51C0D,
    0x02A57C01, 0x02A60004, 0x02A6CC1B, 0x02A77802, 0x02A79401,
    0x02A8A40E, 0x02A90C01, 0x02A93002, 0x02A97004, 0x02A9DC03,
    0x02A9EC03, 0x02AAC001, 0x02AAC803, 0x02AADC02, 0x02AAF802,
    0x02AB0401, 0x02AB7802, 0x02ABAC07, 0x02ABD402, 0x02AD6C01,
    0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, 0x037FFC01,
    0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802, 0x03F7F002,
    0x03F8001A, 0x03F88033, 0x03F95013, 0x03F9A004, 0x03FBFC01,
    0x03FC040F, 0x03FC6807, 0x03FCEC06, 0x03FD6C0B, 0x03FF8007,
    0x03FFA007, 0x03FFE405, 0x04040003, 0x0404DC09, 0x0405E411,
    0x04063003, 0x0406400C, 0x04068001, 0x0407402E, 0x040B8001,
    0x040DD805, 0x040E7C01, 0x040F4001, 0x0415BC01, 0x04215C01,
    0x0421DC02, 0x04247C01, 0x0424FC01, 0x04280403, 0x04281402,
    0x04283004, 0x0428E003, 0x0428FC01, 0x04294009, 0x0429FC01,
    0x042B2001, 0x042B9402, 0x042BC007, 0x042CE407, 0x042E6404,
    0x04349004, 0x043D180B, 0x043D5405, 0x04400003, 0x0440E016,
    0x0441FC04, 0x0442C012, 0x04433401, 0x04440003, 0x04449C0E,
    0x04450004, 0x04451402, 0x0445CC03, 0x04460003, 0x0446CC0E,
    0x04471409, 0x04476C01, 0x04477403, 0x0448B013, 0x044AA401,
    0x044B7C0C, 0x044C0004, 0x044CEC02, 0x044CF807, 0x044D1C02,
    0x044D2C03, 0x044D5C01, 0x044D8802, 0x044D9807, 0x044DC005,
    0x0450D412, 0x04512C05, 0x04516C01, 0x04517402, 0x0452C014,
    0x04531801, 0x0456BC07, 0x0456E020, 0x04577002, 0x0458C014,
    0x0459800D, 0x045AAC0D, 0x045C740F, 0x045CF004, 0x0460B010,
    0x0468040A, 0x0468CC07, 0x0468EC0D, 0x0469440B, 0x046A2813,
    0x046A7805, 0x0470BC08, 0x0470E008, 0x04710405, 0x0471C002,
    0x04724816, 0x0472A40E, 0x0474C406, 0x0474E801, 0x0474F002,
    0x0474FC07, 0x04751C01, 0x04762805, 0x04764002, 0x04764C05,

    0x047BCC06, 0x0491C005, 0x05A9B802, 0x05ABC006, 0x05ACC010,
    0x05AD1002, 0x05BA5C04, 0x05BD442E, 0x05BE3C04, 0x06F27008,
    0x074000F6, 0x07440027, 0x0744A4C0, 0x07480046, 0x074C0057,
    0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401, 0x075CD401,
    0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401, 0x075F0C01,
    0x0760028C, 0x076A6C05, 0x076A840F, 0x07800007, 0x07802011,
    0x07806C07, 0x07808C02, 0x07809805, 0x07A34007, 0x07A51007,

    0x07A57802, 0x07B2B001, 0x07B2C001, 0x07BBC002, 0x07C0002C,
    0x07C0C064, 0x07C2800F, 0x07C2C40F, 0x07C3040F, 0x07C34425,
    0x07C4405C, 0x07C5C03D, 0x07C7981D, 0x07C8402C, 0x07C90009,
    0x07C94002, 0x07C98006, 0x07CC03D5, 0x07DB800D, 0x07DBC00A,
    0x07DC0074, 0x07DE0059, 0x07E0000C, 0x07E04038, 0x07E1400A,
    0x07E18028, 0x07E2401E, 0x07E4000C, 0x07E4402F, 0x07E50031,


    0x07E5CC04, 0x07E5E801, 0x07E5F027, 0x07E6C00A, 0x07E70003,
    0x07E74030, 0x07E9800E, 0x38000401, 0x38008060, 0x380400F0,
  };
  static const unsigned int aAscii[4] = {
    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
  };

  if( (unsigned int)c<128 ){
    return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
................................................................................
** If the argument is a codepoint corresponding to a lowercase letter
** in the ASCII range with a diacritic added, return the codepoint
** of the ASCII letter only. For example, if passed 235 - "LATIN
** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int unicode_remove_diacritic(int c){
  static const unsigned short aDia[] = {
        0,  1797,  1848,  1859,  1891,  1928,  1940,  1995,
     2024,  2040,  2060,  2110,  2168,  2206,  2264,  2286,
     2344,  2383,  2472,  2488,  2516,  2596,  2668,  2732,
     2782,  2842,  2894,  2954,  2984,  3000,  3028,  3336,
     3456,  3696,  3712,  3728,  3744,  3896,  3912,  3928,
     3968,  4008,  4040,  4106,  4138,  4170,  4202,  4234,
     4266,  4296,  4312,  4344,  4408,  4424,  4472,  4504,

     6148,  6198,  6264,  6280,  6360,  6429,  6505,  6529,
    61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
    61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
    62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,


    62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
    62924, 63050, 63082, 63274, 63390,

  };

  static const char aChar[] = {
    '\0', 'a',  'c',  'e',  'i',  'n',  'o',  'u',  'y',  'y',  'a',  'c',
    'd',  'e',  'e',  'g',  'h',  'i',  'j',  'k',  'l',  'n',  'o',  'r',
    's',  't',  'u',  'u',  'w',  'y',  'z',  'o',  'u',  'a',  'i',  'o',
    'u',  'g',  'k',  'o',  'j',  'g',  'n',  'a',  'e',  'i',  'o',  'r',
    'u',  's',  't',  'h',  'a',  'e',  'o',  'y',  '\0', '\0', '\0', '\0',
    '\0', '\0', '\0', '\0', 'a',  'b',  'd',  'd',  'e',  'f',  'g',  'h',
    'h',  'i',  'k',  'l',  'l',  'm',  'n',  'p',  'r',  'r',  's',  't',
    'u',  'v',  'w',  'w',  'x',  'y',  'z',  'h',  't',  'w',  'y',  'a',
    'e',  'i',  'o',  'u',  'y',
















  };

  unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
  int iRes = 0;
  int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1;
  int iLo = 0;
  while( iHi>=iLo ){
................................................................................
      iRes = iTest;
      iLo = iTest+1;
    }else{
      iHi = iTest-1;
    }
  }
  assert( key>=aDia[iRes] );

  return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
}


/*
** Return true if the argument interpreted as a unicode codepoint
** is a diacritical modifier character.
*/
int unicode_is_diacritic(int c){
  unsigned int mask0 = 0x08029FDF;
  unsigned int mask1 = 0x000361F8;
  if( c<768 || c>817 ) return 0;
  return (c < 768+32) ?
      (mask0 & (1 << (c-768))) :
      (mask1 & (1 << (c-768-32)));
}


/*
** Interpret the argument as a unicode codepoint. If the codepoint
** is an upper case character that has a lower case equivalent,
** return the codepoint corresponding to the lower case version.
** Otherwise, return a copy of the argument.
**
** The results are undefined if the value passed to this function
** is less than zero.
*/
int unicode_fold(int c, int bRemoveDiacritic){
  /* Each entry in the following array defines a rule for folding a range
  ** of codepoints to lower case. The rule applies to a range of nRange
  ** codepoints starting at codepoint iCode.
  **
  ** If the least significant bit in flags is clear, then the rule applies
  ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
  ** need to be folded). Or, if it is set, then the rule only applies to
................................................................................
  static const struct TableEntry {
    unsigned short iCode;
    unsigned char flags;
    unsigned char nRange;
  } aEntry[] = {
    {65, 14, 26},          {181, 66, 1},          {192, 14, 23},
    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
    {313, 1, 16},          {330, 1, 46},          {376, 152, 1},
    {377, 1, 6},           {383, 140, 1},         {385, 52, 1},
    {386, 1, 4},           {390, 46, 1},          {391, 0, 1},
    {393, 44, 2},          {395, 0, 1},           {398, 34, 1},
    {399, 40, 1},          {400, 42, 1},          {401, 0, 1},
    {403, 44, 1},          {404, 48, 1},          {406, 54, 1},
    {407, 50, 1},          {408, 0, 1},           {412, 54, 1},
    {413, 56, 1},          {415, 58, 1},          {416, 1, 6},
    {422, 62, 1},          {423, 0, 1},           {425, 62, 1},
    {428, 0, 1},           {430, 62, 1},          {431, 0, 1},
    {433, 60, 2},          {435, 1, 4},           {439, 64, 1},
    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
    {497, 2, 1},           {498, 1, 4},           {502, 158, 1},
    {503, 170, 1},         {504, 1, 40},          {544, 146, 1},
    {546, 1, 18},          {570, 74, 1},          {571, 0, 1},
    {573, 144, 1},         {574, 72, 1},          {577, 0, 1},
    {579, 142, 1},         {580, 30, 1},          {581, 32, 1},
    {582, 1, 10},          {837, 38, 1},          {880, 1, 4},
    {886, 0, 1},           {895, 38, 1},          {902, 20, 1},
    {904, 18, 3},          {908, 28, 1},          {910, 26, 2},
    {913, 14, 17},         {931, 14, 9},          {962, 0, 1},
    {975, 4, 1},           {976, 176, 1},         {977, 178, 1},
    {981, 182, 1},         {982, 180, 1},         {984, 1, 24},
    {1008, 172, 1},        {1009, 174, 1},        {1012, 166, 1},
    {1013, 164, 1},        {1015, 0, 1},          {1017, 188, 1},
    {1018, 0, 1},          {1021, 146, 3},        {1024, 36, 16},
    {1040, 14, 32},        {1120, 1, 34},         {1162, 1, 54},
    {1216, 6, 1},          {1217, 1, 14},         {1232, 1, 96},
    {1329, 24, 38},        {4256, 70, 38},        {4295, 70, 1},
    {4301, 70, 1},         {5112, 186, 6},        {7296, 122, 1},
    {7297, 124, 1},        {7298, 126, 1},        {7299, 130, 2},
    {7301, 128, 1},        {7302, 132, 1},        {7303, 134, 1},
    {7304, 96, 1},         {7312, 138, 43},       {7357, 138, 3},
    {7680, 1, 150},        {7835, 168, 1},        {7838, 116, 1},
    {7840, 1, 96},         {7944, 186, 8},        {7960, 186, 6},
    {7976, 186, 8},        {7992, 186, 8},        {8008, 186, 6},
    {8025, 187, 8},        {8040, 186, 8},        {8072, 186, 8},
    {8088, 186, 8},        {8104, 186, 8},        {8120, 186, 2},
    {8122, 162, 2},        {8124, 184, 1},        {8126, 120, 1},
    {8136, 160, 4},        {8140, 184, 1},        {8152, 186, 2},
    {8154, 156, 2},        {8168, 186, 2},        {8170, 154, 2},
    {8172, 188, 1},        {8184, 148, 2},        {8186, 150, 2},
    {8188, 184, 1},        {8486, 118, 1},        {8490, 112, 1},
    {8491, 114, 1},        {8498, 12, 1},         {8544, 8, 16},
    {8579, 0, 1},          {9398, 10, 26},        {11264, 24, 47},
    {11360, 0, 1},         {11362, 108, 1},       {11363, 136, 1},
    {11364, 110, 1},       {11367, 1, 6},         {11373, 104, 1},
    {11374, 106, 1},       {11375, 100, 1},       {11376, 102, 1},
    {11378, 0, 1},         {11381, 0, 1},         {11390, 98, 2},
    {11392, 1, 100},       {11499, 1, 4},         {11506, 0, 1},
    {42560, 1, 46},        {42624, 1, 28},        {42786, 1, 14},
    {42802, 1, 62},        {42873, 1, 4},         {42877, 94, 1},
    {42878, 1, 10},        {42891, 0, 1},         {42893, 86, 1},
    {42896, 1, 4},         {42902, 1, 20},        {42922, 80, 1},
    {42923, 76, 1},        {42924, 78, 1},        {42925, 82, 1},
    {42926, 80, 1},        {42928, 90, 1},        {42929, 84, 1},
    {42930, 88, 1},        {42931, 68, 1},        {42932, 1, 6},

    {43888, 92, 80},       {65313, 14, 26},
  };
  static const unsigned short aiOff[] = {
   1,     2,     8,     15,    16,    26,    28,    32,
   34,    37,    38,    40,    48,    63,    64,    69,
   71,    79,    80,    116,   202,   203,   205,   206,
   207,   209,   210,   211,   213,   214,   217,   218,
   219,   775,   928,   7264,  10792, 10795, 23217, 23221,
   23228, 23231, 23254, 23256, 23275, 23278, 26672, 30204,
   35267, 54721, 54753, 54754, 54756, 54787, 54793, 54809,
   57153, 57274, 57921, 58019, 58363, 59314, 59315, 59324,
   59325, 59326, 59332, 59356, 61722, 62528, 65268, 65341,
   65373, 65406, 65408, 65410, 65415, 65424, 65436, 65439,
   65450, 65462, 65472, 65476, 65478, 65480, 65482, 65488,
   65506, 65511, 65514, 65521, 65527, 65528, 65529,

  };

  int ret = c;

  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );

  if( c<128 ){
................................................................................
    assert( iRes>=0 && c>=aEntry[iRes].iCode );
    p = &aEntry[iRes];
    if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
      ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
      assert( ret>0 );
    }


    if( bRemoveDiacritic ) ret = unicode_remove_diacritic(ret);

  }

  else if( c>=66560 && c<66600 ){
    ret = c + 40;
  }
  else if( c>=66736 && c<66772 ){
    ret = c + 40;

Changes to src/update.c.

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
                      db_get_int("autosync-tries", 1), 1) ){
      fossil_fatal("update abandoned due to sync failure");
    }
  }

  /* Create any empty directories now, as well as after the update,
  ** so changes in settings are reflected now */
  if( !dryRunFlag ) ensure_empty_dirs_created(0);

  if( internalUpdate ){
    tid = internalUpdate;
  }else if( g.argc>=3 ){
    if( fossil_strcmp(g.argv[2], "current")==0 ){
      /* If VERSION is "current", then use the same algorithm to find the
      ** target as if VERSION were omitted. */
................................................................................
  }

  if( tid==0 ){
    return;
  }

  db_begin_transaction();
  db_multi_exec(
     "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
     filename_collation()
  );
  vfile_check_signature(vid, CKSIG_ENOTFILE);
  if( !dryRunFlag && !internalUpdate ) undo_begin();
  if( load_vfile_from_rid(tid) && !forceMissingFlag ){
    fossil_fatal("missing content, unable to update");
  };

  /*
................................................................................
        ** file but keep the edited version around. */
        fossil_print("CONFLICT %s - edited locally but deleted by update\n",
                     zName);
        nConflict++;
      }else{
        fossil_print("REMOVE %s\n", zName);
        if( !dryRunFlag && !internalUpdate ) undo_save(zName);
        if( !dryRunFlag ){
          char *zDir;
          file_delete(zFullPath);
          zDir = file_dirname(zName);
          while( zDir!=0 ){
            char *zNext;
            db_multi_exec("INSERT OR IGNORE INTO dir_to_delete(name)"
                          "VALUES(%Q)", zDir);
            zNext = db_changes() ? file_dirname(zDir) : 0;
            fossil_free(zDir);
            zDir = zNext;
          }
        }
      }
    }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
      /* Merge the changes in the current tree into the target version */
      Blob r, t, v;
      int rc;
      if( nameChng ){
        fossil_print("MERGE %s -> %s\n", zName, zNewName);
................................................................................

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  if( dryRunFlag ){
    db_end_transaction(1);  /* With --dry-run, rollback changes */
  }else{
    char *zPwd;
    ensure_empty_dirs_created(1);
    sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
                            file_rmdir_sql_function, 0, 0);
    zPwd = file_getcwd(0,0);
    db_multi_exec(
      "SELECT rmdir(%Q||name) FROM dir_to_delete"
      " WHERE (%Q||name)<>%Q ORDER BY name DESC",
      g.zLocalRoot, g.zLocalRoot, zPwd
    );
    fossil_free(zPwd);
    if( g.argc<=3 ){
      /* All files updated.  Shift the current checkout to the target. */
      db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
      checkout_set_all_exe(tid);
      manifest_to_disk(tid);
      db_set_checkout(tid);
    }else{
................................................................................
    db_end_transaction(0);
  }
}

/*
** Create empty directories specified by the empty-dirs setting.
*/
void ensure_empty_dirs_created(int clearDirTable){
  char *zEmptyDirs = db_get("empty-dirs", 0);
  if( zEmptyDirs!=0 ){
    int i;
    Blob dirName;
    Blob dirsList;

    zEmptyDirs = fossil_strdup(zEmptyDirs);
................................................................................
          if( file_mkfolder(zPath, RepoFILE, 0, 1)!=0 ) {
            fossil_warning("couldn't create directory %s as "
                           "required by empty-dirs setting", zDir);
          }
          break;
        }
        case 1: { /* exists, and is a directory */
          /* make sure this directory is not on the delete list */
          if( clearDirTable ){
            db_multi_exec(
              "DELETE FROM dir_to_delete WHERE name=%Q", zDir
            );
          }
          break;
        }
        case 2: { /* exists, but isn't a directory */
          fossil_warning("file %s found, but a directory is required "
                         "by empty-dirs setting", zDir);
        }
      }







|







 







<
<
<
<







 







<
<
|
<
<
<
<
<
<
<
<
<
<







 







<
|
<
<
<
<
<
<
<
<
<







 







|







 







|
<
<
<
<
<







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
225
226
227
228
229
230
231




232
233
234
235
236
237
238
...
453
454
455
456
457
458
459


460










461
462
463
464
465
466
467
...
564
565
566
567
568
569
570

571









572
573
574
575
576
577
578
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
...
611
612
613
614
615
616
617
618





619
620
621
622
623
624
625
                      db_get_int("autosync-tries", 1), 1) ){
      fossil_fatal("update abandoned due to sync failure");
    }
  }

  /* Create any empty directories now, as well as after the update,
  ** so changes in settings are reflected now */
  if( !dryRunFlag ) ensure_empty_dirs_created();

  if( internalUpdate ){
    tid = internalUpdate;
  }else if( g.argc>=3 ){
    if( fossil_strcmp(g.argv[2], "current")==0 ){
      /* If VERSION is "current", then use the same algorithm to find the
      ** target as if VERSION were omitted. */
................................................................................
  }

  if( tid==0 ){
    return;
  }

  db_begin_transaction();




  vfile_check_signature(vid, CKSIG_ENOTFILE);
  if( !dryRunFlag && !internalUpdate ) undo_begin();
  if( load_vfile_from_rid(tid) && !forceMissingFlag ){
    fossil_fatal("missing content, unable to update");
  };

  /*
................................................................................
        ** file but keep the edited version around. */
        fossil_print("CONFLICT %s - edited locally but deleted by update\n",
                     zName);
        nConflict++;
      }else{
        fossil_print("REMOVE %s\n", zName);
        if( !dryRunFlag && !internalUpdate ) undo_save(zName);


        if( !dryRunFlag ) file_delete(zFullPath);










      }
    }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
      /* Merge the changes in the current tree into the target version */
      Blob r, t, v;
      int rc;
      if( nameChng ){
        fossil_print("MERGE %s -> %s\n", zName, zNewName);
................................................................................

  /*
  ** Clean up the mid and pid VFILE entries.  Then commit the changes.
  */
  if( dryRunFlag ){
    db_end_transaction(1);  /* With --dry-run, rollback changes */
  }else{

    ensure_empty_dirs_created();









    if( g.argc<=3 ){
      /* All files updated.  Shift the current checkout to the target. */
      db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
      checkout_set_all_exe(tid);
      manifest_to_disk(tid);
      db_set_checkout(tid);
    }else{
................................................................................
    db_end_transaction(0);
  }
}

/*
** Create empty directories specified by the empty-dirs setting.
*/
void ensure_empty_dirs_created(void){
  char *zEmptyDirs = db_get("empty-dirs", 0);
  if( zEmptyDirs!=0 ){
    int i;
    Blob dirName;
    Blob dirsList;

    zEmptyDirs = fossil_strdup(zEmptyDirs);
................................................................................
          if( file_mkfolder(zPath, RepoFILE, 0, 1)!=0 ) {
            fossil_warning("couldn't create directory %s as "
                           "required by empty-dirs setting", zDir);
          }
          break;
        }
        case 1: { /* exists, and is a directory */
          /* do nothing - required directory exists already */





          break;
        }
        case 2: { /* exists, but isn't a directory */
          fossil_warning("file %s found, but a directory is required "
                         "by empty-dirs setting", zDir);
        }
      }

Changes to src/vfile.c.

357
358
359
360
361
362
363


















364
365
366
367
368
369
370
    blob_reset(&content);
    db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
                  file_mtime(zName, RepoFILE), id);
  }
  db_finalize(&q);
}



















/*
** Check to see if the directory named in zPath is the top of a checkout.
** In other words, check to see if directory pPath contains a file named
** "_FOSSIL_" or ".fslckout".  Return true or false.
*/
int vfile_top_of_checkout(const char *zPath){
  char *zFile;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    blob_reset(&content);
    db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
                  file_mtime(zName, RepoFILE), id);
  }
  db_finalize(&q);
}


/*
** Delete from the disk every file in VFILE vid.
*/
void vfile_unlink(int vid){
  Stmt q;
  db_prepare(&q, "SELECT %Q || pathname FROM vfile"
                 " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName;

    zName = db_column_text(&q, 0);
    file_delete(zName);
  }
  db_finalize(&q);
  db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
}

/*
** Check to see if the directory named in zPath is the top of a checkout.
** In other words, check to see if directory pPath contains a file named
** "_FOSSIL_" or ".fslckout".  Return true or false.
*/
int vfile_top_of_checkout(const char *zPath){
  char *zFile;

Changes to src/wiki.c.

488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504

505
506
507
508
509
510
511
...
683
684
685
686
687
688
689


690
691
692
693
694
695
696
...
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
  }
  zMimetype = wiki_filter_mimetypes(zMimetype);
  if( !g.isHome ){
    if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
     && wiki_special_permission(zPageName)
    ){
      if( db_get_boolean("wysiwyg-wiki", 0) ){
        style_submenu_element("Edit", "%R/wikiedit?name=%T&wysiwyg=1",
                              zPageName);
      }else{
        style_submenu_element("Edit", "%R/wikiedit?name=%T", zPageName);
      }
    }else if( rid && g.perm.ApndWiki ){
      style_submenu_element("Edit", "%R/wikiappend?name=%T", zPageName);
    }
    if( g.perm.Hyperlink ){
      style_submenu_element("History", "%R/whistory?name=%T", zPageName);

    }
  }
  style_set_current_page("%T?name=%T", g.zPath, zPageName);
  wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
  wiki_standard_submenu(submenuFlags);
  if( zBody[0]==0 ){
    @ <i>This page has been deleted</i>
................................................................................
  eType = wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "Edit: ");
  if( rid && !isSandbox && g.perm.ApndWiki ){
    if( g.perm.Attach ){
      style_submenu_element("Attach",
           "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
           g.zTop, zPageName, g.zTop, zPageName);
    }


  }
  if( !goodCaptcha ){
    @ <p class="generalError">Error:  Incorrect security code.</p>
  }
  blob_zero(&wiki);
  while( fossil_isspace(zBody[0]) ) zBody++;
  blob_append(&wiki, zBody, -1);
................................................................................
    blob_reset(&html);
    @ <br />
    @ <input type="submit" name="edit-markup" value="Markup Editor"
    @  onclick='return confirm("Switching to markup-mode\nwill erase your WYSIWYG\nedits. Continue?")' />
  }
  login_insert_csrf_secret();
  if( havePreview ){
    if( isWysiwyg || zBody[0] ){
      @ <input type="submit" name="submit" value="Apply These Changes" />
    }else{
      @ <input type="submit" name="submit" value="Delete This Wiki Page" />
    }
  }
  @ <input type="hidden" name="name" value="%h(zPageName)" />
  @ <input type="submit" name="cancel" value="Cancel"







|
|

|

<
<


|
>







 







>
>







 







|







488
489
490
491
492
493
494
495
496
497
498
499


500
501
502
503
504
505
506
507
508
509
510
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
  }
  zMimetype = wiki_filter_mimetypes(zMimetype);
  if( !g.isHome ){
    if( ((rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki))
     && wiki_special_permission(zPageName)
    ){
      if( db_get_boolean("wysiwyg-wiki", 0) ){
        style_submenu_element("Edit", "%s/wikiedit?name=%T&wysiwyg=1",
             g.zTop, zPageName);
      }else{
        style_submenu_element("Edit", "%s/wikiedit?name=%T", g.zTop, zPageName);
      }


    }
    if( g.perm.Hyperlink ){
      style_submenu_element("History", "%s/whistory?name=%T",
           g.zTop, zPageName);
    }
  }
  style_set_current_page("%T?name=%T", g.zPath, zPageName);
  wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "");
  wiki_standard_submenu(submenuFlags);
  if( zBody[0]==0 ){
    @ <i>This page has been deleted</i>
................................................................................
  eType = wiki_page_header(WIKITYPE_UNKNOWN, zPageName, "Edit: ");
  if( rid && !isSandbox && g.perm.ApndWiki ){
    if( g.perm.Attach ){
      style_submenu_element("Attach",
           "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
           g.zTop, zPageName, g.zTop, zPageName);
    }
    style_submenu_element("Append", "%s/wikiappend?name=%T&mimetype=%s",
         g.zTop, zPageName, zMimetype);
  }
  if( !goodCaptcha ){
    @ <p class="generalError">Error:  Incorrect security code.</p>
  }
  blob_zero(&wiki);
  while( fossil_isspace(zBody[0]) ) zBody++;
  blob_append(&wiki, zBody, -1);
................................................................................
    blob_reset(&html);
    @ <br />
    @ <input type="submit" name="edit-markup" value="Markup Editor"
    @  onclick='return confirm("Switching to markup-mode\nwill erase your WYSIWYG\nedits. Continue?")' />
  }
  login_insert_csrf_secret();
  if( havePreview ){
    if( zBody[0] ){
      @ <input type="submit" name="submit" value="Apply These Changes" />
    }else{
      @ <input type="submit" name="submit" value="Delete This Wiki Page" />
    }
  }
  @ <input type="hidden" name="name" value="%h(zPageName)" />
  @ <input type="submit" name="cancel" value="Cancel"

Changes to src/wikiformat.c.

1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128

1129
1130
1131
1132
1133
1134
1135
** is not the UUID of a ticket, return false.
*/
static int is_ticket(
  const char *zTarget,    /* Ticket UUID */
  int *pClosed            /* True if the ticket is closed */
){
  static Stmt q;

  int n;
  int rc;
  char zLower[HNAME_MAX+1];
  char zUpper[HNAME_MAX+1];
  n = strlen(zTarget);
  memcpy(zLower, zTarget, n+1);
  canonical16(zLower, n+1);
  memcpy(zUpper, zLower, n+1);
  zUpper[n-1]++;
  if( !db_static_stmt_is_init(&q) ){
    const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
    db_static_prepare(&q,
      "SELECT %s FROM ticket "
      " WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr",
      zClosedExpr /*safe-for-%s*/
    );

  }
  db_bind_text(&q, ":lwr", zLower);
  db_bind_text(&q, ":upr", zUpper);
  if( db_step(&q)==SQLITE_ROW ){
    rc = 1;
    *pClosed = db_column_int(&q, 0);
  }else{







>









|






>







1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
** is not the UUID of a ticket, return false.
*/
static int is_ticket(
  const char *zTarget,    /* Ticket UUID */
  int *pClosed            /* True if the ticket is closed */
){
  static Stmt q;
  static int once = 1;
  int n;
  int rc;
  char zLower[HNAME_MAX+1];
  char zUpper[HNAME_MAX+1];
  n = strlen(zTarget);
  memcpy(zLower, zTarget, n+1);
  canonical16(zLower, n+1);
  memcpy(zUpper, zLower, n+1);
  zUpper[n-1]++;
  if( once ){
    const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
    db_static_prepare(&q,
      "SELECT %s FROM ticket "
      " WHERE tkt_uuid>=:lwr AND tkt_uuid<:upr",
      zClosedExpr /*safe-for-%s*/
    );
    once = 0;
  }
  db_bind_text(&q, ":lwr", zLower);
  db_bind_text(&q, ":upr", zUpper);
  if( db_step(&q)==SQLITE_ROW ){
    rc = 1;
    *pClosed = db_column_int(&q, 0);
  }else{

Changes to src/xfer.c.

2286
2287
2288
2289
2290
2291
2292














2293
2294

2295
2296
2297
2298
2299
2300
2301
      */
      if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
        if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
          char *zMsg = blob_terminate(&xfer.aToken[1]);
          defossilize(zMsg);
          fossil_force_newline();
          fossil_print("Error: %s\n", zMsg);














          blob_appendf(&xfer.err, "server says: %s\n", zMsg);
          nErr++;

          break;
        }
      }else

      /* Unknown message */
      if( xfer.nToken>0 ){
        if( blob_str(&xfer.aToken[0])[0]=='<' ){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>







2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
      */
      if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
        if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
          char *zMsg = blob_terminate(&xfer.aToken[1]);
          defossilize(zMsg);
          fossil_force_newline();
          fossil_print("Error: %s\n", zMsg);
          if( fossil_strcmp(zMsg, "login failed")==0 ){
            if( nCycle<2 ){
              g.url.passwd = 0;
              go = 1;
              if( g.cgiOutput==0 ){
                g.url.flags |= URL_PROMPT_PW;
                g.url.flags &= ~URL_PROMPTED;
                url_prompt_for_password();
                url_remember();
              }
            }else{
              nErr++;
            }
          }else{
            blob_appendf(&xfer.err, "server says: %s\n", zMsg);
            nErr++;
          }
          break;
        }
      }else

      /* Unknown message */
      if( xfer.nToken>0 ){
        if( blob_str(&xfer.aToken[0])[0]=='<' ){

Changes to win/Makefile.dmc.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
950
951
952
953
954
955
956
957
958
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB

SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\deltafunc$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

................................................................................
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export file finfo foci forum fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
................................................................................

$(OBJDIR)\deltacmd$O : deltacmd_.c deltacmd.h
	$(TCC) -o$@ -c deltacmd_.c

deltacmd_.c : $(SRCDIR)\deltacmd.c
	+translate$E $** > $@

$(OBJDIR)\deltafunc$O : deltafunc_.c deltafunc.h
	$(TCC) -o$@ -c deltafunc_.c

deltafunc_.c : $(SRCDIR)\deltafunc.c
	+translate$E $** > $@

$(OBJDIR)\descendants$O : descendants_.c descendants.h
	$(TCC) -o$@ -c descendants_.c

descendants_.c : $(SRCDIR)\descendants.c
	+translate$E $** > $@

$(OBJDIR)\diff$O : diff_.c diff.h
................................................................................
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h deltafunc_.c:deltafunc.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h webmail_.c:webmail.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers







|

|







 







|







 







<
<
<
<
<
<







 







|

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
289
290
291
292
293
294
295






296
297
298
299
300
301
302
...
944
945
946
947
948
949
950
951
952
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32 dnsapi

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB

SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c file_.c finfo_.c foci_.c forum_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\capabilities$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\webmail$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

................................................................................
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd descendants diff diffcmd dispatch doc encode etag event export file finfo foci forum fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
................................................................................

$(OBJDIR)\deltacmd$O : deltacmd_.c deltacmd.h
	$(TCC) -o$@ -c deltacmd_.c

deltacmd_.c : $(SRCDIR)\deltacmd.c
	+translate$E $** > $@







$(OBJDIR)\descendants$O : descendants_.c descendants.h
	$(TCC) -o$@ -c descendants_.c

descendants_.c : $(SRCDIR)\descendants.c
	+translate$E $** > $@

$(OBJDIR)\diff$O : diff_.c diff.h
................................................................................
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h capabilities_.c:capabilities.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h repolist_.c:repolist.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h setupuser_.c:setupuser.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h smtp_.c:smtp.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h webmail_.c:webmail.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers

Changes to win/Makefile.mingw.

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
....
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
....
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2r
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/deltafunc.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/deltafunc_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/deltafunc.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................
		$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
		$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
		$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
		$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
		$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
		$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/deltafunc_.c:$(OBJDIR)/deltafunc.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/deltafunc_.c:	$(SRCDIR)/deltafunc.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/deltafunc.c >$@

$(OBJDIR)/deltafunc.o:	$(OBJDIR)/deltafunc_.c $(OBJDIR)/deltafunc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltafunc.o -c $(OBJDIR)/deltafunc_.c

$(OBJDIR)/deltafunc.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers







|







 







<







 







<







 







<







 







<







 







<
<
<
<
<
<
<
<







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
461
462
463
464
465
466
467

468
469
470
471
472
473
474
...
672
673
674
675
676
677
678

679
680
681
682
683
684
685
...
810
811
812
813
814
815
816

817
818
819
820
821
822
823
....
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
....
1501
1502
1503
1504
1505
1506
1507








1508
1509
1510
1511
1512
1513
1514
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2q
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \

  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \

  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \

 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................
		$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
		$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
		$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
		$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
		$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
		$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \

		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers









$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

Changes to win/Makefile.mingw.mistachkin.

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
....
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
....
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2r
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/deltafunc.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/deltafunc_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/deltafunc.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................
		$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
		$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
		$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
		$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
		$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
		$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/deltafunc_.c:$(OBJDIR)/deltafunc.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers

$(OBJDIR)/deltafunc_.c:	$(SRCDIR)/deltafunc.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/deltafunc.c >$@

$(OBJDIR)/deltafunc.o:	$(OBJDIR)/deltafunc_.c $(OBJDIR)/deltafunc.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltafunc.o -c $(OBJDIR)/deltafunc_.c

$(OBJDIR)/deltafunc.h:	$(OBJDIR)/headers

$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers







|







 







<







 







<







 







<







 







<







 







<
<
<
<
<
<
<
<







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
461
462
463
464
465
466
467

468
469
470
471
472
473
474
...
672
673
674
675
676
677
678

679
680
681
682
683
684
685
...
810
811
812
813
814
815
816

817
818
819
820
821
822
823
....
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
....
1501
1502
1503
1504
1505
1506
1507








1508
1509
1510
1511
1512
1513
1514
endif

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLDIR = $(SRCDIR)/../compat/openssl-1.0.2q
OPENSSLINCDIR = $(OPENSSLDIR)/include
OPENSSLLIBDIR = $(OPENSSLDIR)

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
................................................................................
  $(SRCDIR)/comformat.c \
  $(SRCDIR)/configure.c \
  $(SRCDIR)/content.c \
  $(SRCDIR)/cookies.c \
  $(SRCDIR)/db.c \
  $(SRCDIR)/delta.c \
  $(SRCDIR)/deltacmd.c \

  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
................................................................................
  $(OBJDIR)/comformat_.c \
  $(OBJDIR)/configure_.c \
  $(OBJDIR)/content_.c \
  $(OBJDIR)/cookies_.c \
  $(OBJDIR)/db_.c \
  $(OBJDIR)/delta_.c \
  $(OBJDIR)/deltacmd_.c \

  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
................................................................................
 $(OBJDIR)/comformat.o \
 $(OBJDIR)/configure.o \
 $(OBJDIR)/content.o \
 $(OBJDIR)/cookies.o \
 $(OBJDIR)/db.o \
 $(OBJDIR)/delta.o \
 $(OBJDIR)/deltacmd.o \

 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
................................................................................
		$(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h \
		$(OBJDIR)/configure_.c:$(OBJDIR)/configure.h \
		$(OBJDIR)/content_.c:$(OBJDIR)/content.h \
		$(OBJDIR)/cookies_.c:$(OBJDIR)/cookies.h \
		$(OBJDIR)/db_.c:$(OBJDIR)/db.h \
		$(OBJDIR)/delta_.c:$(OBJDIR)/delta.h \
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \

		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
................................................................................
	$(TRANSLATE) $(SRCDIR)/deltacmd.c >$@

$(OBJDIR)/deltacmd.o:	$(OBJDIR)/deltacmd_.c $(OBJDIR)/deltacmd.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/deltacmd.o -c $(OBJDIR)/deltacmd_.c

$(OBJDIR)/deltacmd.h:	$(OBJDIR)/headers









$(OBJDIR)/descendants_.c:	$(SRCDIR)/descendants.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/descendants.c >$@

$(OBJDIR)/descendants.o:	$(OBJDIR)/descendants_.c $(OBJDIR)/descendants.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/descendants.o -c $(OBJDIR)/descendants_.c

$(OBJDIR)/descendants.h:	$(OBJDIR)/headers

Changes to win/Makefile.msc.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
....
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
....
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914

# Enable support for the SQLite Encryption Extension?
!ifndef USE_SEE
USE_SEE = 0
!endif

!if $(FOSSIL_ENABLE_SSL)!=0
SSLDIR    = $(B)\compat\openssl-1.0.2r
SSLINCDIR = $(SSLDIR)\inc32
!if $(FOSSIL_DYNAMIC_BUILD)!=0
SSLLIBDIR = $(SSLDIR)\out32dll
!else
SSLLIBDIR = $(SSLDIR)\out32
!endif
SSLLFLAGS = /nologo /opt:ref /debug
................................................................................
        comformat_.c \
        configure_.c \
        content_.c \
        cookies_.c \
        db_.c \
        delta_.c \
        deltacmd_.c \
        deltafunc_.c \
        descendants_.c \
        diff_.c \
        diffcmd_.c \
        dispatch_.c \
        doc_.c \
        encode_.c \
        etag_.c \
................................................................................
        $(OX)\configure$O \
        $(OX)\content$O \
        $(OX)\cookies$O \
        $(OX)\cson_amalgamation$O \
        $(OX)\db$O \
        $(OX)\delta$O \
        $(OX)\deltacmd$O \
        $(OX)\deltafunc$O \
        $(OX)\descendants$O \
        $(OX)\diff$O \
        $(OX)\diffcmd$O \
        $(OX)\dispatch$O \
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\etag$O \
................................................................................
	echo $(OX)\configure.obj >> $@
	echo $(OX)\content.obj >> $@
	echo $(OX)\cookies.obj >> $@
	echo $(OX)\cson_amalgamation.obj >> $@
	echo $(OX)\db.obj >> $@
	echo $(OX)\delta.obj >> $@
	echo $(OX)\deltacmd.obj >> $@
	echo $(OX)\deltafunc.obj >> $@
	echo $(OX)\descendants.obj >> $@
	echo $(OX)\diff.obj >> $@
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\dispatch.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\etag.obj >> $@
................................................................................

$(OX)\deltacmd$O : deltacmd_.c deltacmd.h
	$(TCC) /Fo$@ -c deltacmd_.c

deltacmd_.c : $(SRCDIR)\deltacmd.c
	translate$E $** > $@

$(OX)\deltafunc$O : deltafunc_.c deltafunc.h
	$(TCC) /Fo$@ -c deltafunc_.c

deltafunc_.c : $(SRCDIR)\deltafunc.c
	translate$E $** > $@

$(OX)\descendants$O : descendants_.c descendants.h
	$(TCC) /Fo$@ -c descendants_.c

descendants_.c : $(SRCDIR)\descendants.c
	translate$E $** > $@

$(OX)\diff$O : diff_.c diff.h
................................................................................
			comformat_.c:comformat.h \
			configure_.c:configure.h \
			content_.c:content.h \
			cookies_.c:cookies.h \
			db_.c:db.h \
			delta_.c:delta.h \
			deltacmd_.c:deltacmd.h \
			deltafunc_.c:deltafunc.h \
			descendants_.c:descendants.h \
			diff_.c:diff.h \
			diffcmd_.c:diffcmd.h \
			dispatch_.c:dispatch.h \
			doc_.c:doc.h \
			encode_.c:encode.h \
			etag_.c:etag.h \







|







 







<







 







<







 







<







 







<
<
<
<
<
<







 







<







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
401
402
403
404
405
406
407

408
409
410
411
412
413
414
...
611
612
613
614
615
616
617

618
619
620
621
622
623
624
...
812
813
814
815
816
817
818

819
820
821
822
823
824
825
....
1206
1207
1208
1209
1210
1211
1212






1213
1214
1215
1216
1217
1218
1219
....
1891
1892
1893
1894
1895
1896
1897

1898
1899
1900
1901
1902
1903
1904

# Enable support for the SQLite Encryption Extension?
!ifndef USE_SEE
USE_SEE = 0
!endif

!if $(FOSSIL_ENABLE_SSL)!=0
SSLDIR    = $(B)\compat\openssl-1.0.2q
SSLINCDIR = $(SSLDIR)\inc32
!if $(FOSSIL_DYNAMIC_BUILD)!=0
SSLLIBDIR = $(SSLDIR)\out32dll
!else
SSLLIBDIR = $(SSLDIR)\out32
!endif
SSLLFLAGS = /nologo /opt:ref /debug
................................................................................
        comformat_.c \
        configure_.c \
        content_.c \
        cookies_.c \
        db_.c \
        delta_.c \
        deltacmd_.c \

        descendants_.c \
        diff_.c \
        diffcmd_.c \
        dispatch_.c \
        doc_.c \
        encode_.c \
        etag_.c \
................................................................................
        $(OX)\configure$O \
        $(OX)\content$O \
        $(OX)\cookies$O \
        $(OX)\cson_amalgamation$O \
        $(OX)\db$O \
        $(OX)\delta$O \
        $(OX)\deltacmd$O \

        $(OX)\descendants$O \
        $(OX)\diff$O \
        $(OX)\diffcmd$O \
        $(OX)\dispatch$O \
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\etag$O \
................................................................................
	echo $(OX)\configure.obj >> $@
	echo $(OX)\content.obj >> $@
	echo $(OX)\cookies.obj >> $@
	echo $(OX)\cson_amalgamation.obj >> $@
	echo $(OX)\db.obj >> $@
	echo $(OX)\delta.obj >> $@
	echo $(OX)\deltacmd.obj >> $@

	echo $(OX)\descendants.obj >> $@
	echo $(OX)\diff.obj >> $@
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\dispatch.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\etag.obj >> $@
................................................................................

$(OX)\deltacmd$O : deltacmd_.c deltacmd.h
	$(TCC) /Fo$@ -c deltacmd_.c

deltacmd_.c : $(SRCDIR)\deltacmd.c
	translate$E $** > $@







$(OX)\descendants$O : descendants_.c descendants.h
	$(TCC) /Fo$@ -c descendants_.c

descendants_.c : $(SRCDIR)\descendants.c
	translate$E $** > $@

$(OX)\diff$O : diff_.c diff.h
................................................................................
			comformat_.c:comformat.h \
			configure_.c:configure.h \
			content_.c:content.h \
			cookies_.c:cookies.h \
			db_.c:db.h \
			delta_.c:delta.h \
			deltacmd_.c:deltacmd.h \

			descendants_.c:descendants.h \
			diff_.c:diff.h \
			diffcmd_.c:diffcmd.h \
			dispatch_.c:dispatch.h \
			doc_.c:doc.h \
			encode_.c:encode.h \
			etag_.c:etag.h \

Changes to www/admin-v-setup.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# The Differences Between the Setup and Admin User Capabilities

Several of the Fossil user capabilities form a clear power hierarchy.
Mathematically speaking:

> *Setup > Admin > Moderator > User > Subscriber > Anonymous > Nobody*

This document explains the distinction between the first two. For the
others, see:

* [How Moderation Works](./forum.wiki#moderation)

* [Users vs Subscribers](./alerts.md#uvs)

................................................................................
        to 0 to Setup only while allowing Admin-only users to change it
        from 0 to 1. Fossil doesn't currently allow that.</p>

    *   <p><b>Risky</b>: The <tt>https-login</tt> setting falls under
        the "Security" section above, but it should probably never be
        adjusted by Admin-only users. Sites that want it on will never
        want it to be disabled without a very good reason.</p>

        <p>There is also an inverse risk: if the site has a front-end
        HTTPS proxy that uses HTTP to communicate over localhost to
        Fossil, enabling this setting will create an infinite redirect
        loop! (Ask me how I know.)</p>

    *   <p><b>Dangerous</b>: The <tt>email-send-command</tt> setting
        could allow a rogue Admin to run arbitrary commands on the host






|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# The Differences Between the Setup and Admin User Capabilities

Several of the Fossil user capabilities form a clear power hierarchy.
Mathematically speaking:

> *Setup > Admin > Moderator > User > Subscriber > Anonymous > Nobody*
    
This document explains the distinction between the first two. For the
others, see:

* [How Moderation Works](./forum.wiki#moderation)

* [Users vs Subscribers](./alerts.md#uvs)

................................................................................
        to 0 to Setup only while allowing Admin-only users to change it
        from 0 to 1. Fossil doesn't currently allow that.</p>

    *   <p><b>Risky</b>: The <tt>https-login</tt> setting falls under
        the "Security" section above, but it should probably never be
        adjusted by Admin-only users. Sites that want it on will never
        want it to be disabled without a very good reason.</p>
        
        <p>There is also an inverse risk: if the site has a front-end
        HTTPS proxy that uses HTTP to communicate over localhost to
        Fossil, enabling this setting will create an infinite redirect
        loop! (Ask me how I know.)</p>

    *   <p><b>Dangerous</b>: The <tt>email-send-command</tt> setting
        could allow a rogue Admin to run arbitrary commands on the host

Changes to www/backoffice.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
178
179
180
181
182
183
184
185
186
187
188
189
Backoffice
==========

This is technical documentation about the internal workings of Fossil.
Ordinary Fossil users do not need to know about anything covered by this
document.  The information here is intended for people who want to enhance
or extend the Fossil code, or who just want a deeper understanding of
the internal workings of Fossil.

What Is The Backoffice
----------------------

The backoffice is a mechanism used by a
[Fossil server](/doc/trunk/www/server.wiki) to do low-priority
background work that is not directly related to the user interface.  Here
are some examples of the kinds of work that backoffice performs:

  1.  Sending email alerts and notifications
  2.  Sending out daily digests of email notifications
  3.  Other background email handling chores
................................................................................
request.

The backoffice is not a daemon.  Each backoffice process runs for a short
while and then exits.  This helps keep Fossil easy to manage, since there
are no daemons to start and stop.  To upgrade Fossil to a new version,
you simply replace the older "fossil" executable with the newer one, and
the backoffice processes will (within a minute or so) start using the new
one.  (Upgrading the executable on Windows is more complicated, since on
Windows it is not possible to replace an executable file that is in active
use.  But Windows users probably already know this.)

The backoffice is serialized and rate limited.  No more than a single
backoffice process will be running at once, and backoffice runs will not
occur more frequently than once every 60 seconds.

If a Fossil server is idle, then no backoffice processes will be running.
That means there are no extra processes sitting around taking up memory
and process table slots for seldom accessed repositories.
The backoffice is an on-demand system.
A busy repository will usually have a backoffice
running at all times.  But an infrequently accessed repository will only have
backoffice processes running for a minute or two following the most recent
access.

................................................................................
However, the daily digest of email notifications is handled by the
backoffice.  If a Fossil server can sometimes go more than a day without
being accessed, then the automatic backoffice will never run, and the
daily digest might not go out until somebody does visit a webpage.
If this is a problem, an adminstrator can set up a cron job to
periodically run:

>   fossil backoffice _REPOSITORY_

That command will cause backoffice processing to occur immediately.
Note that this is almost never necessary for an internet-facing
Fossil repository, since most repositories will get multiple accesses
per day from random robots, which will be sufficient to kick off the
daily digest emails.  And even for a private server, if there is very
little traffic, then the daily digests are probably a no-op anyhow
................................................................................
>  fossil test-backoffice-lease -R _REPOSITORY_

If a system has been idle for a long time, then there will be no
backoffice processes.  (Either the process id entries in the lease
will be zero, or there will exist no process associated with the
process id.) When a new web request comes in, the system
sees that no backoffice process is active and so it kicks off a separate
process to run backoffice.

The new backoffice process becomes the "current" process.  It sets a
lease expiration time for itself to be 60 seconds in the future.
Then it does the backoffice processing and exits.  Note that usually
the backoffice process will exit long before its lease expires.  That
is ok.  The lease is there to limit the rate at which backoffice processes
run.

If a new backoffice process starts up and sees that the "current" lease has
................................................................................
can be fixed.  The "backoffice-logfile" setting is the name of a log
file onto which is appended a short message everything a backoffice
process actually starts to do the backoffice work.  This log file can
be used to verify that backoffice really is running, if there is any
doubt.  The "backoffice-disable" setting prevents automatic backoffice
processing, if true.  Use this to completely disable backoffice processing
that occurs automatically after each HTTP request.  The "backoffice-disable"
setting does not affect the operation of the manual
"fossil backoffice" command.
Most installations should leave "backoffice-nodelay" and "backoffice-disable"
set to their default values of off and
leave "backoffice-logfile" unset or set to an empty string.






|





|







 







|
|







|







 







|







 







|

|







 







|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
178
179
180
181
182
183
184
185
186
187
188
189
Backoffice
==========

This is technical documentation about the internal workings of Fossil.
Ordinary Fossil users do not need to know about anything covered by this
document.  The information here is intended for people who want to enhance
or extend the Fossil code, or who just want a deeper understanding of 
the internal workings of Fossil.

What Is The Backoffice
----------------------

The backoffice is a mechanism used by a 
[Fossil server](/doc/trunk/www/server.wiki) to do low-priority
background work that is not directly related to the user interface.  Here
are some examples of the kinds of work that backoffice performs:

  1.  Sending email alerts and notifications
  2.  Sending out daily digests of email notifications
  3.  Other background email handling chores
................................................................................
request.

The backoffice is not a daemon.  Each backoffice process runs for a short
while and then exits.  This helps keep Fossil easy to manage, since there
are no daemons to start and stop.  To upgrade Fossil to a new version,
you simply replace the older "fossil" executable with the newer one, and
the backoffice processes will (within a minute or so) start using the new
one.  (Upgrading the executable on Windows is more complicated, since on 
Windows it is not possible to replace an executable file that is in active 
use.  But Windows users probably already know this.)

The backoffice is serialized and rate limited.  No more than a single
backoffice process will be running at once, and backoffice runs will not
occur more frequently than once every 60 seconds.

If a Fossil server is idle, then no backoffice processes will be running.
That means there are no extra processes sitting around taking up memory 
and process table slots for seldom accessed repositories.
The backoffice is an on-demand system.
A busy repository will usually have a backoffice
running at all times.  But an infrequently accessed repository will only have
backoffice processes running for a minute or two following the most recent
access.

................................................................................
However, the daily digest of email notifications is handled by the
backoffice.  If a Fossil server can sometimes go more than a day without
being accessed, then the automatic backoffice will never run, and the
daily digest might not go out until somebody does visit a webpage.
If this is a problem, an adminstrator can set up a cron job to
periodically run:

>   fossil backoffice -R _REPOSITORY_

That command will cause backoffice processing to occur immediately.
Note that this is almost never necessary for an internet-facing
Fossil repository, since most repositories will get multiple accesses
per day from random robots, which will be sufficient to kick off the
daily digest emails.  And even for a private server, if there is very
little traffic, then the daily digests are probably a no-op anyhow
................................................................................
>  fossil test-backoffice-lease -R _REPOSITORY_

If a system has been idle for a long time, then there will be no
backoffice processes.  (Either the process id entries in the lease
will be zero, or there will exist no process associated with the
process id.) When a new web request comes in, the system
sees that no backoffice process is active and so it kicks off a separate
process to run backoffice.  

The new backoffice process becomes the "current" process.  It sets a 
lease expiration time for itself to be 60 seconds in the future.
Then it does the backoffice processing and exits.  Note that usually
the backoffice process will exit long before its lease expires.  That
is ok.  The lease is there to limit the rate at which backoffice processes
run.

If a new backoffice process starts up and sees that the "current" lease has
................................................................................
can be fixed.  The "backoffice-logfile" setting is the name of a log
file onto which is appended a short message everything a backoffice
process actually starts to do the backoffice work.  This log file can
be used to verify that backoffice really is running, if there is any
doubt.  The "backoffice-disable" setting prevents automatic backoffice
processing, if true.  Use this to completely disable backoffice processing
that occurs automatically after each HTTP request.  The "backoffice-disable"
setting does not affect the operation of the manual 
"fossil backoffice" command.
Most installations should leave "backoffice-nodelay" and "backoffice-disable"
set to their default values of off and
leave "backoffice-logfile" unset or set to an empty string.

Changes to www/blockchain.md.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Some people have come to associate blockchain with cryptocurrency, however,
and since Fossil has nothing to do with cryptocurrency, the claim that
Fossil is build around blockchain is met with skepticism.  The key thing
to note here is that cryptocurrency implementations like BitCoin are
built around blockchain, but they are not synonymous with blockchain.
Blockchain is a much broader concept.  Blockchain is a mechanism for
constructed a distributed ledger of transactions.
Yes, you can use a distributed
ledger to implement a cryptocurrency, but you can also use a distributed
ledger to implement a version control system, and probably many other kinds
of applications as well.  Blockchain is a much broader idea than
cryptocurrency.

[(1)]: https://en.wikipedia.org/wiki/Blockchain







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Some people have come to associate blockchain with cryptocurrency, however,
and since Fossil has nothing to do with cryptocurrency, the claim that
Fossil is build around blockchain is met with skepticism.  The key thing
to note here is that cryptocurrency implementations like BitCoin are
built around blockchain, but they are not synonymous with blockchain.
Blockchain is a much broader concept.  Blockchain is a mechanism for
constructed a distributed ledger of transactions.  
Yes, you can use a distributed
ledger to implement a cryptocurrency, but you can also use a distributed
ledger to implement a version control system, and probably many other kinds
of applications as well.  Blockchain is a much broader idea than
cryptocurrency.

[(1)]: https://en.wikipedia.org/wiki/Blockchain

Changes to www/build.wiki.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<h2>2.0 Compiling</h2>

<ol>
<li value="5">
<p>Unpack the ZIP or tarball you downloaded then
<b>cd</b> into the directory created.</p></li>

<li><i>(Optional, Debian-compatible Linux only)</i>
Make sure you have all the necessary tools and libraries at hand by running:
<b>sudo apt install tcl-dev tk libssl-dev</b>.

<li><i>(Optional, Unix only)</i>
Run <b>./configure</b> to construct a makefile.

<ol type="a">
<li><p>
The build system for Fossil on Unix-like systems assumes that the
OpenSSL development and runtime files are available on your system,
................................................................................
file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to
detect and use the latest installed version of MSVC.<br><br>To enable
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
first <a href="https://www.openssl.org/source/">download the official
source code for OpenSSL</a> and extract it to an appropriately named
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
[/tree?ci=trunk&name=compat | compat] directory (e.g.
"<b>compat/openssl-1.0.2r</b>"), then make sure that some recent
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
and finally run one of the following commands:
<blockquote><pre>
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
</pre></blockquote>
<blockquote><pre>
buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
................................................................................
"openssl-devel" packages installed first.
</ol>
</ol>

<h2>3.0 Installing</h2>

<ol>
<li value="9">
<p>The finished binary is named "fossil" (or "fossil.exe" on Windows).
Put this binary in a
directory that is somewhere on your PATH environment variable.
It does not matter where.</p>

<li>
<p><b>(Optional:)</b>







<
<
<
<







 







|







 







|







71
72
73
74
75
76
77




78
79
80
81
82
83
84
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<h2>2.0 Compiling</h2>

<ol>
<li value="5">
<p>Unpack the ZIP or tarball you downloaded then
<b>cd</b> into the directory created.</p></li>





<li><i>(Optional, Unix only)</i>
Run <b>./configure</b> to construct a makefile.

<ol type="a">
<li><p>
The build system for Fossil on Unix-like systems assumes that the
OpenSSL development and runtime files are available on your system,
................................................................................
file "<b>win\buildmsvc.bat</b>" may be used and it will attempt to
detect and use the latest installed version of MSVC.<br><br>To enable
the optional <a href="https://www.openssl.org/">OpenSSL</a> support,
first <a href="https://www.openssl.org/source/">download the official
source code for OpenSSL</a> and extract it to an appropriately named
"<b>openssl-X.Y.ZA</b>" subdirectory within the local
[/tree?ci=trunk&name=compat | compat] directory (e.g.
"<b>compat/openssl-1.0.2q</b>"), then make sure that some recent
<a href="http://www.perl.org/">Perl</a> binaries are installed locally,
and finally run one of the following commands:
<blockquote><pre>
nmake /f Makefile.msc FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
</pre></blockquote>
<blockquote><pre>
buildmsvc.bat FOSSIL_ENABLE_SSL=1 FOSSIL_BUILD_SSL=1 PERLDIR=C:\full\path\to\Perl\bin
................................................................................
"openssl-devel" packages installed first.
</ol>
</ol>

<h2>3.0 Installing</h2>

<ol>
<li value="8">
<p>The finished binary is named "fossil" (or "fossil.exe" on Windows).
Put this binary in a
directory that is somewhere on your PATH environment variable.
It does not matter where.</p>

<li>
<p><b>(Optional:)</b>

Changes to www/changes.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<title>Change Log</title>

<a name='v2_9'></a>
<h2>Changes for Version 2.9 (pending)</h2>

  *  Added the [/help?cmd=git|fossil git export] command and instructions
     for [./mirrortogithub.md|creating a GitHub mirror of a Fossil project].
  *  Improved handling of relative hyperlinks on the
     [/help?cmd=/artifact|/artifact] pages for wiki. For example,
     hyperlinks and the lizard &lt;img&gt; now work correctly
     for both [/artifact/2ff24ab0887cf522] and
     [/doc/0d7ac90d575004c2415/www/index.wiki].
  *  For the "[/help?cmd=update|fossil update]" and
     "[/help?cmd=checkout|fossil checkout]" commands, if a
     managed file is removed because it is no longer part of the target
     check-in and the directory containing the file is empty after the
     file is removed and the directory is not the current working
     directory and is not on the [/help?cmd=empty-dirs|empty-dirs]
     list, then also remove the directory.
  *  Update internal Unicode character tables, used in regular expression
     handling, from version 11.0 to 12.0.
  *  In "[/help?cmd=regexp|fossil regexp]", "[/help?cmd=grep|fossil grep]"
     and the TH1 "regexp" command, the -nocase option now removes multiple
     diacritics from the same character (derived from SQLite's
     remove_diacritics=2)

<a name='v2_8'></a>
<h2>Changes for Version 2.8 (2019-02-20)</h2>

  *  Show cherry-pick merges as dotted lines on the timeline graph.
     &rarr; The "fossil rebuild" command must be run to create and
     populate the new "cherrypick" table in the repository in order
     for this feature to operate.
  *  Add the ability to associate branches, check-ins, and tags with
     specially-named Wiki pages. This gives the ability to better
     document branches and tags, and provide more documentation on
     check-ins beyond the check-in comment.  The associated Wiki is
     automatically displayed on /info pages for check-ins, and on
     /timeline?r=BRANCH and /timeline?t=TAG pages for branches and
     tags. This feature is on by default, but can be disabled in on
     the Admin/Wiki page.
  *  Enhance the repository list page (shown for example by
     "fossil all ui") so that it shows the name and last check-in
     time for each project.  The implementation of the repository
     list page is now broken out into a separate source file (repolist.c).
  *  Allow users with Forum Supervisor permission ('6') to add Forum
................................................................................
     version of the Wiki page named in the timeline, not to the latest
     version.
  *  Enhancements to the "amend", "tag", and "reparent" commands, including
     adding options --override-date, --override-user, and --dry-run.
  *  Add the global --comment-format command-line option and the
     comment-format setting to control the display of the command-line
     timeline.
  *  Change the "fossil reparent" command so that it only works from
     within an active checkout.
  *  On the /setup_ucap_list, show administrators how many users have
     each capability.  The counts are a hyperlink to the /setup_ulist
     page showing the subset of users that have that capability.
  *  Provide the ability to redirect all HTTP pages to HTTPS.  Formerly
     one could cause this to occur for the /login page only.  That option
     still exists, but the redirect can now also be done for all pages.
................................................................................
     Formerly, user capabilities were letters from &#91;a-z&#93;, but with the
     enhancements, the supply of lower case letters was exhausted.
     User capabilities are now letters in &#91;a-zA-Z0-9&#93;.
  *  The built-in skins are now responsive, providing better layout on
     small screens, including mobile devices.
  *  The default skin now includes a hamburger menu that is generated
     by the [/sitemap] page.
  *  All of the built-in skins now use a
     [https://en.wikipedia.org/wiki/Content_Security_Policy|Content Security Policy (CSP)]
     to help prevent cross-site injection and forgery attacks.  There are no known
     vulnerabilities in Fossil.  The added CSP does not fix anything; it merely adds
     another layer of defense.
  *  The [/sitemap] and other list pages show as multiple columns if
     the viewing window is wide enough.
  *  There is an optional "js" file for each skin that can be used to


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|






|







 







|







 







|







1
2
























3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<title>Change Log</title>

























<a name='v2_8'></a>
<h2>Changes for Version 2.8 (2019-02-20)</h2>

  *  Show cherry-pick merges as dotted lines on the timeline graph.
     &rarr; The "fossil rebuild" command must be run to create and
     populate the new "cherrypick" table in the repository in order 
     for this feature to operate.
  *  Add the ability to associate branches, check-ins, and tags with
     specially-named Wiki pages. This gives the ability to better
     document branches and tags, and provide more documentation on
     check-ins beyond the check-in comment.  The associated Wiki is
     automatically displayed on /info pages for check-ins, and on
     /timeline?r=BRANCH and /timeline?t=TAG pages for branches and 
     tags. This feature is on by default, but can be disabled in on
     the Admin/Wiki page.
  *  Enhance the repository list page (shown for example by
     "fossil all ui") so that it shows the name and last check-in
     time for each project.  The implementation of the repository
     list page is now broken out into a separate source file (repolist.c).
  *  Allow users with Forum Supervisor permission ('6') to add Forum
................................................................................
     version of the Wiki page named in the timeline, not to the latest
     version.
  *  Enhancements to the "amend", "tag", and "reparent" commands, including
     adding options --override-date, --override-user, and --dry-run.
  *  Add the global --comment-format command-line option and the
     comment-format setting to control the display of the command-line
     timeline.
  *  Change the "fossil reparent" command so that it only works from 
     within an active checkout.
  *  On the /setup_ucap_list, show administrators how many users have
     each capability.  The counts are a hyperlink to the /setup_ulist
     page showing the subset of users that have that capability.
  *  Provide the ability to redirect all HTTP pages to HTTPS.  Formerly
     one could cause this to occur for the /login page only.  That option
     still exists, but the redirect can now also be done for all pages.
................................................................................
     Formerly, user capabilities were letters from &#91;a-z&#93;, but with the
     enhancements, the supply of lower case letters was exhausted.
     User capabilities are now letters in &#91;a-zA-Z0-9&#93;.
  *  The built-in skins are now responsive, providing better layout on
     small screens, including mobile devices.
  *  The default skin now includes a hamburger menu that is generated
     by the [/sitemap] page.
  *  All of the built-in skins now use a 
     [https://en.wikipedia.org/wiki/Content_Security_Policy|Content Security Policy (CSP)]
     to help prevent cross-site injection and forgery attacks.  There are no known
     vulnerabilities in Fossil.  The added CSP does not fix anything; it merely adds
     another layer of defense.
  *  The [/sitemap] and other list pages show as multiple columns if
     the viewing window is wide enough.
  *  There is an optional "js" file for each skin that can be used to

Changes to www/delta_format.wiki.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19

20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<title>Fossil Delta Format</title>
<h1>1.0 Overview</h1>


<p>Fossil achieves efficient storage and low-bandwidth synchronization
through the use of delta-compression.  Instead of storing
or transmitting the complete content of an artifact, Fossil stores or
transmits only the changes relative to a related artifact.
</p>

<p>This document describes the delta-encoding format used by Fossil.
The intended audience is developers working on either
<a href="index.wiki">Fossil</a> itself, or on tools compatible with
Fossil. Understanding of this document is <em>not</em> required for
ordinary users of Fossil.  This document is an implementation detail.</p>


<p>This document only describes the delta file format.  A 
[./delta_encoder_algorithm.wiki|separate document] describes one possible
algorithm for generating deltas in this format.</p>


<h2>1.1 Sample Software And Analysis Tools</h2>


<p>The core routines used to generate and apply deltas in this format
are contained in the [../src/delta.c|delta.c] source file.  Interface
logic, including "test-*" commands to directly manipulate deltas are
contained in the [../src/deltacmd.c|deltacmd.c] source file.  SQL functions
to create, apply, and analyze deltas are implemented by code in the
[../src/deltafunc.c|deltafunc.c] source file.

<p>The following command-line tools are available to create and apply
deltas and to test the delta logic:

   *   [/help?cmd=test-delta|fossil test-delta] &rarr; Run self-tests of
       the delta logic

   *   [/help?cmd=test-delta-create|fossil test-delta-create X Y] &rarr; compute
       a delta that converts file X into file Y.  Output that delta.

   *   [/help?cmd=test-delta-apply|fossil test-delta-apply X D] &rarr; apply
       delta D to input file X and output the result.

   *   [/help?cmd=test-delta-analyze|fossil test-delta-analyze X Y] &rarr; compute
       and delta that converts file X into file Y but instead of writing the
       delta to output, write performance information about the delta.

<p>When running the [/help?cmd=sqlite3|fossil sql] command to get an
interactive SQL session connected to the repository, the following
additional SQL functions are provided:

   *   <b>delta_create(</b><i>X</i><b>,</b><i>Y</i><b>)</b> &rarr;
       Compute a data that carries blob X into blob Y and return that delta
       as a blob.

   *   <b>delta_apply(</b><i>X</i><b>,</b><i>D</i><b>)</b> &rarr;
       Apply delta D to input blob X return a new blob which is the result.


   *   <b>delta_output_size(</b><i>D</i>)</b> &rarr;
       Return the size of the output that would result from applying delta D.

   *   <b>delta_parse(</b><i>D</i>)</b> &rarr; This is a table-valued function
       that returns one row for the header, for the trailer, and for each segment
       in delta D.


<a name="structure"></a><h1>2.0 Structure</h1>
<img src="delta1.gif" align="left" hspace="10">

<p>A delta consists of three parts, a "header", a "trailer", and a
"segment-list" between them.</p>

<p>Both header and trailer provide information about the target
helping the decoder, and the segment-list describes how the target can
be constructed from the original.</p>

<a name="header"></a><h2>2.1 Header</h2>
<img src="delta6.gif" align="left" hspace="10">

<p>The header consists of a single number followed by a newline
character (ASCII 0x0a). The number is the length of the target in
bytes.</p>

<p>This means that, given a delta, the decoder can compute the size of
the target (and allocate any necessary memory based on that) by simply
reading the first line of the delta and decoding the number found
there. In other words, before it has to decode everything else.</p>

<a name="trailer"></a><h2>2.2 Trailer</h2>
<img src="delta5.gif" align="left" hspace="10">

<p>The trailer consists of a single number followed by a semicolon (ASCII
0x3b). This number is a checksum of the target and can be used by a
decoder to verify that the delta applied correctly, reconstructing the
target from the original.</p>

................................................................................
2^32-1. A target whose length is not a multiple of 4 is padded with
0-bytes (ASCII 0x00) at the end.</p>

<p>By putting this information at the end of the delta a decoder has
it available immediately after the target has been reconstructed
fully.</p>

<a name="slist"></a><h2>2.3 Segment-List</h2>
<img src="delta2.gif" align="left" hspace="10">

<p>The segment-list of a delta describes how to create the target from
the original by a combination of inserting literal byte-sequences and
copying ranges of bytes from the original. This is where the
compression takes place, by encoding the large common parts of
original and target in small copy instructions.</p>

<p>The target is constructed from beginning to end, with the data
generated by each instruction appended after the data of all previous
instructions, with no gaps.</p>

<a name="insertlit"></a><h3>2.3.1 Insert Literal</h3>

<p>A literal is specified by two elements, the size of the literal in
bytes, and the bytes of the literal itself.</p>

<img src="delta4.gif" align="left" hspace="10">
<p>The length is written first, followed by a colon character (ASCII
0x3a), followed by the bytes of the literal.</p>

<a name="copyrange"></a><h3>2.3.2 Copy Range</h3>

<p>A range to copy is specified by two numbers, the offset of the
first byte in the original to copy, and the size of the range, in
bytes. The size zero is special, its usage indicates that the range
extends to the end of the original.</p>

<img src="delta3.gif" align="left" hspace="10">
<p>The length is written first, followed by an "at" character (ASCII
0x40), then the offset, followed by a comma (ASCII 0x2c).</p>

<a name="intcoding"></a><h1>3.0 Encoding of integers</h1>

<p>
The format currently handles only 32 bit integer numbers. They are
written base-64 encoded, MSB first, and without leading
"0"-characters, except if they are significant (i.e. 0 => "0").
</p>

<p>
The base-64 coding is described in
<a href="http://www.ietf.org/rfc/rfc3548.txt">RFC 3548</a>.
</p>

<a name="examples"></a><h1>4.0 Examples</h1>

<a name="examplesint"></a><h2>4.1 Integer encoding</h2>

<table border=1>
<tr>
<th>Value</th>
<th>Encoding</th>
</tr>
<tr>
................................................................................
</tr>
<tr>
<td>-1101438770</td>
<td>2zMM3E</td>
</tr>
</table>

<a name="examplesdelta"></a><h2>4.2 Delta encoding</h2>

<p>An example of a delta using the specified encoding is:</p>

<table border=1><tr><td><pre>
1Xb
4E@0,2:thFN@4C,6:scenda1B@Jd,6:scenda5x@Kt,6:pieces79@Qt,F: Example: eskil~E@Y0,2zMM3E;</pre>
</td></tr></table>
................................................................................

  *  Ticketing interface (expand this bullet)

</pre></td></tr></table>



<a name="notes"></a><h1>Notes</h1>

<ul>
<li>Pure text files generate a pure text delta.
</li>
<li>Binary files generate a delta that may contain some binary data.
</li>
<li>The delta encoding does not attempt to compress the content.
It was considered to be much
more sensible to do compression using a separate general-purpose
compression library, like <a href="http://www.zlib.net">zlib</a>.
</li>
</ul>

|
>



|



|

|
|
<

>
|
|
|
<
>
|
<
>
|
|
|
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|









|











|







 







|












|








|










|












|

|







 







|







 







|












1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19

20
21

22
23
24
25



26




































27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<title>Fossil Delta Format</title>
<nowiki>
<h2>Abstract</h2>

<p>Fossil achieves efficient storage and low-bandwidth synchronization
through the use of delta-compression.  Instead of storing
or transmitting the complete content of an artifact, fossil stores or
transmits only the changes relative to a related artifact.
</p>

<p>This document describes the delta-encoding format used by fossil.
The intended audience is developers working on either
<a href="index.wiki">fossil</a> itself, or on tools compatible with
fossil.</p>


<p>Note that the delta-encoding is not a fundamental element of the
state of a fossil repository.  A state of a fossil repository is
defined by the uncompressed and undeltaed content of all artifacts.
The fact the artifacts

are stored on disk using this delta-encoding format is merely an
optimization.  One could, in theory, create an entirely new and

compatible implementation of fossil that used a different delta-encoding
or did no delta-encoding at all.  However, experience has shown that
the delta-encoding described here is both efficient to compute and
results in very small deltas, so its continued use is recommended.</p>








































<a name="structure"></a><h2>1.0 Structure</h2>
<img src="delta1.gif" align="left" hspace="10">

<p>A delta consists of three parts, a "header", a "trailer", and a
"segment-list" between them.</p>

<p>Both header and trailer provide information about the target
helping the decoder, and the segment-list describes how the target can
be constructed from the original.</p>

<a name="header"></a><h3>1.1 Header</h3>
<img src="delta6.gif" align="left" hspace="10">

<p>The header consists of a single number followed by a newline
character (ASCII 0x0a). The number is the length of the target in
bytes.</p>

<p>This means that, given a delta, the decoder can compute the size of
the target (and allocate any necessary memory based on that) by simply
reading the first line of the delta and decoding the number found
there. In other words, before it has to decode everything else.</p>

<a name="trailer"></a><h3>1.2 Trailer</h3>
<img src="delta5.gif" align="left" hspace="10">

<p>The trailer consists of a single number followed by a semicolon (ASCII
0x3b). This number is a checksum of the target and can be used by a
decoder to verify that the delta applied correctly, reconstructing the
target from the original.</p>

................................................................................
2^32-1. A target whose length is not a multiple of 4 is padded with
0-bytes (ASCII 0x00) at the end.</p>

<p>By putting this information at the end of the delta a decoder has
it available immediately after the target has been reconstructed
fully.</p>

<a name="slist"></a><h3>1.3 Segment-List</h3>
<img src="delta2.gif" align="left" hspace="10">

<p>The segment-list of a delta describes how to create the target from
the original by a combination of inserting literal byte-sequences and
copying ranges of bytes from the original. This is where the
compression takes place, by encoding the large common parts of
original and target in small copy instructions.</p>

<p>The target is constructed from beginning to end, with the data
generated by each instruction appended after the data of all previous
instructions, with no gaps.</p>

<a name="insertlit"></a><h4>1.3.1 Insert Literal</h4>

<p>A literal is specified by two elements, the size of the literal in
bytes, and the bytes of the literal itself.</p>

<img src="delta4.gif" align="left" hspace="10">
<p>The length is written first, followed by a colon character (ASCII
0x3a), followed by the bytes of the literal.</p>

<a name="copyrange"></a><h4>1.3.2 Copy Range</h4>

<p>A range to copy is specified by two numbers, the offset of the
first byte in the original to copy, and the size of the range, in
bytes. The size zero is special, its usage indicates that the range
extends to the end of the original.</p>

<img src="delta3.gif" align="left" hspace="10">
<p>The length is written first, followed by an "at" character (ASCII
0x40), then the offset, followed by a comma (ASCII 0x2c).</p>

<a name="intcoding"></a><h2>2.0 Encoding of integers</h2>

<p>
The format currently handles only 32 bit integer numbers. They are
written base-64 encoded, MSB first, and without leading
"0"-characters, except if they are significant (i.e. 0 => "0").
</p>

<p>
The base-64 coding is described in
<a href="http://www.ietf.org/rfc/rfc3548.txt">RFC 3548</a>.
</p>

<a name="examples"></a><h2>3.0 Examples</h2>

<a name="examplesint"></a><h3>3.1 Integer encoding</h3>

<table border=1>
<tr>
<th>Value</th>
<th>Encoding</th>
</tr>
<tr>
................................................................................
</tr>
<tr>
<td>-1101438770</td>
<td>2zMM3E</td>
</tr>
</table>

<a name="examplesdelta"></a><h3>3.2 Delta encoding</h3>

<p>An example of a delta using the specified encoding is:</p>

<table border=1><tr><td><pre>
1Xb
4E@0,2:thFN@4C,6:scenda1B@Jd,6:scenda5x@Kt,6:pieces79@Qt,F: Example: eskil~E@Y0,2zMM3E;</pre>
</td></tr></table>
................................................................................

  *  Ticketing interface (expand this bullet)

</pre></td></tr></table>



<a name="notes"></a><h2>Notes</h2>

<ul>
<li>Pure text files generate a pure text delta.
</li>
<li>Binary files generate a delta that may contain some binary data.
</li>
<li>The delta encoding does not attempt to compress the content.
It was considered to be much
more sensible to do compression using a separate general-purpose
compression library, like <a href="http://www.zlib.net">zlib</a>.
</li>
</ul>

Changes to www/env-opts.md.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
global setting should be used to force the case sensitivity to the
most sensible condition.

`--chdir DIRECTORY`: Change to the named directory before processing
any commands.


`--comfmtflags NUMBER`
`--comment-format NUMBER`: Specify flags that control how check-in comments
and certain other text outputs are formatted for display. The flags are
individual bits in `NUMBER`, which must be specified in base 10:

  * _0_ &mdash; Uses the revised algorithm with no special handling.

  * _1_ &mdash; Uses the legacy algorithm, other flags are ignored.







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
global setting should be used to force the case sensitivity to the
most sensible condition.

`--chdir DIRECTORY`: Change to the named directory before processing
any commands.


`--comfmtflags NUMBER`  
`--comment-format NUMBER`: Specify flags that control how check-in comments
and certain other text outputs are formatted for display. The flags are
individual bits in `NUMBER`, which must be specified in base 10:

  * _0_ &mdash; Uses the revised algorithm with no special handling.

  * _1_ &mdash; Uses the legacy algorithm, other flags are ignored.

Changes to www/fileformat.wiki.

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
[#wikichng | wiki artifact].

The <b>Z</b> card is the required checksum over the rest of the artifact.

<a name="forum"></a>
<h3>2.8 Forum Posts</h3>

Forum posts are intended as a mechanism for users and developers to
discuss a project.  Forum posts are like messages on a mailing list.

The following cards are allowed on an forum post artifact:

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>G</b> <i>thread-root</i><br />
................................................................................
<b>P</b> <i>parent-artifact-id</i><br />
<b>U</b> <i>user-name</i><br />
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
<b>Z</b> <i>checksum</i>
</blockquote>

Every forum post must have either one <b>I</b> card and one <b>G</b> card
or one <b>H</b> card.
Forum posts are organized into topic threads.  The initial
post for a thread (the root post) has an <b>H</b> card giving the title or
subject for that thread.  The argument to the <b>H</b> card is a string
in the same format as a comment string in a <b>C</b> card.
All follow-up posts have an <b>I</b> card that
indicates which prior post in the same thread the current forum
post is replying to, and a <b>G</b> card specifying the root post for







|







 







|







527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
[#wikichng | wiki artifact].

The <b>Z</b> card is the required checksum over the rest of the artifact.

<a name="forum"></a>
<h3>2.8 Forum Posts</h3>

Forum posts are intended as a mechanism for users and developers to 
discuss a project.  Forum posts are like messages on a mailing list.

The following cards are allowed on an forum post artifact:

<blockquote>
<b>D</b> <i>time-and-date-stamp</i><br />
<b>G</b> <i>thread-root</i><br />
................................................................................
<b>P</b> <i>parent-artifact-id</i><br />
<b>U</b> <i>user-name</i><br />
<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br />
<b>Z</b> <i>checksum</i>
</blockquote>

Every forum post must have either one <b>I</b> card and one <b>G</b> card
or one <b>H</b> card.  
Forum posts are organized into topic threads.  The initial
post for a thread (the root post) has an <b>H</b> card giving the title or
subject for that thread.  The argument to the <b>H</b> card is a string
in the same format as a comment string in a <b>C</b> card.
All follow-up posts have an <b>I</b> card that
indicates which prior post in the same thread the current forum
post is replying to, and a <b>G</b> card specifying the root post for

Changes to www/forum.wiki.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
     nearest wifi router or cellular data tower.

  *  <b>Interlink with Other Fossil-Managed Artifacts:</b> Because forum
     posts are normal Fossil artifacts, you can interlink them with
     other Fossil artifacts using short internal links: link to forum
     threads from a [./tickets.wiki | ticket], link to a wiki document
     from a forum post, etc.

  *  <b>Durable Links:</b> Once you create a valid internal artifact
     link in Fossil, it <em>remains</em> valid, durably. With
     third-party forum software and mailing list search engines, your
     links are only valid until the third-party component changes its
     URL scheme or disappears from the web.

  *  <b>Role-Based Access Control:</b> The forum uses the same







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
     nearest wifi router or cellular data tower.

  *  <b>Interlink with Other Fossil-Managed Artifacts:</b> Because forum
     posts are normal Fossil artifacts, you can interlink them with
     other Fossil artifacts using short internal links: link to forum
     threads from a [./tickets.wiki | ticket], link to a wiki document
     from a forum post, etc.
     
  *  <b>Durable Links:</b> Once you create a valid internal artifact
     link in Fossil, it <em>remains</em> valid, durably. With
     third-party forum software and mailing list search engines, your
     links are only valid until the third-party component changes its
     URL scheme or disappears from the web.

  *  <b>Role-Based Access Control:</b> The forum uses the same

Deleted www/image-format-vs-repo-size.ipynb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image Format vs Fossil Repository Size\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "`pip install jupyter matplotlib pandas wand`\n",
    "\n",
    "\n",
    "## Running\n",
    "\n",
    "The next cell generates the test repositories. This takes about half a minute due to the time needed for all the file I/O.\n",
    "\n",
    "The one after that produces the bar chart from the collected data.\n",
    "\n",
    "\n",
    "## Discussion\n",
    "\n",
    "That is kept in [a separate document](image-format-vs-repo-size.md) so we can share that document with Fossil's Markdown renderer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import random\n",
    "import time\n",
    "\n",
    "from wand.color import Color\n",
    "from wand.drawing import Drawing\n",
    "from wand.image import Image\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "size = 256\n",
    "iterations = 10\n",
    "\n",
    "repo_sizes = []\n",
    "\n",
    "formats = ['JPEG', 'BMP', 'TIFF', 'PNG']\n",
    "for f in formats:\n",
    "    ext = f.lower()\n",
    "    tdir = 'test' + '-' + ext\n",
    "    repo = tdir + '.fossil'\n",
    "    ifn = 'test.' + ext\n",
    "    ipath = os.path.join(tdir, ifn)\n",
    "    rs = []\n",
    "    \n",
    "    def add_repo_size():\n",
    "        rs.append(os.path.getsize(repo) / 1024.0 / 1024.0)\n",
    "\n",
    "    try:\n",
    "        # Create test repo\n",
    "        if not os.path.exists(tdir): os.mkdir(tdir, 0700)\n",
    "        cmd = 'cd {0} ; fossil init ../{1} && fossil open ../{1} && fossil set binary-glob \"*.{2}\"'.format(\n",
    "            tdir, repo, ext\n",
    "        )\n",
    "        if os.system(cmd) != 0:\n",
    "            raise RuntimeError('Failed to create test repo ' + repo)\n",
    "        add_repo_size()\n",
    "\n",
    "        # Create test image and add it to the repo\n",
    "        img = Image(width = size, height = size, depth = 8,\n",
    "                    background = 'white')\n",
    "        img.alpha_channel = 'remove'\n",
    "        img.evaluate('gaussiannoise', 1.0)\n",
    "        img.save(filename = ipath)\n",
    "        cmd = 'cd {0} ; fossil add {1} && fossil ci -m \"initial\"'.format(\n",
    "            tdir, ifn\n",
    "        )\n",
    "        if os.system(cmd) != 0:\n",
    "            raise RuntimeError('Failed to add ' + ifn + ' to test repo')\n",
    "        #print \"Created test repo \" + repo + \" for format \" + f + \".\"\n",
    "        add_repo_size()\n",
    "\n",
    "        # Change a random pixel to a random RGB value and check it in\n",
    "        # $iterations times.\n",
    "        for i in range(iterations):\n",
    "            with Drawing() as draw:\n",
    "                x = random.randint(0, size - 1)\n",
    "                y = random.randint(0, size - 1)\n",
    "\n",
    "                r = random.randint(0, 255)\n",
    "                g = random.randint(0, 255)\n",
    "                b = random.randint(0, 255)\n",
    "                \n",
    "                draw.fill_color = Color('rgb({0},{1},{2})'.format(\n",
    "                    r, g, b\n",
    "                ))\n",
    "                draw.color(x, y, 'point')\n",
    "                draw(img)\n",
    "                img.save(filename = ipath)\n",
    "                \n",
    "                # ImageMagick appears to use some kind of asynchronous\n",
    "                # file saving mechanism, so we have to give it time to\n",
    "                # complete.\n",
    "                time.sleep(1.0)\n",
    "  \n",
    "                cmd = 'cd {0} ; fossil ci -m \"change {1} step {2}\"'.format(\n",
    "                    tdir, f, i\n",
    "                )\n",
    "                if os.system(cmd) != 0:\n",
    "                    raise RuntimeError('Failed to change ' + f + ' image, step ' + str(i))\n",
    "                add_repo_size()\n",
    "                \n",
    "        # Repo complete for this format\n",
    "        repo_sizes.append(pd.Series(rs, name=f))\n",
    "\n",
    "    finally:\n",
    "        if os.path.exists(ipath): os.remove(ipath)\n",
    "        if os.path.exists(tdir):\n",
    "            os.system('cd ' + tdir + ' ; fossil close -f')\n",
    "            os.rmdir(tdir)\n",
    "        if os.path.exists(repo): os.remove(repo)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%config InlineBackend.figure_formats = ['svg']\n",
    "\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "data = pd.concat(repo_sizes, axis=1)\n",
    "mpl.rcParams['figure.figsize'] = (7, 4)\n",
    "plt.rcParams['axes.facecolor'] = 'white'\n",
    "data.plot(kind = 'bar', colormap = 'coolwarm',\n",
    "          grid = False, width = 0.8,\n",
    "          edgecolor = 'white', linewidth = 2)\n",
    "plt.savefig('image-format-vs-repo-size.svg')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































































































































































































































































































Deleted www/image-format-vs-repo-size.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# Image Format vs Fossil Repo Size

## The Problem

Fossil has a [delta compression][dc] feature which removes redundant
information from a file when checking in a subsequent version.¹ That
delta is then [zlib][zl]-compressed before being stored in the Fossil
repository database file.

These two steps have a few practical consequences when it comes to
storing already-compressed files:

1.  Binary data compression algorithms such as zlib turn the file data
    into [pseudorandom noise][prn].  Typical data compression algorithms
    are not [hash functions][hf], where the goal is that a change to
    each bit in the input has a statistically even chance of changing
    every bit in the output, but because they do approach that
    pathalogical condition, pre-compressed data tends to defeat Fossil’s
    delta compression algorithm, there being so little correlation
    between two different outputs from the binary data compression
    algorithm.

2.  An ideal lossless binary data compression algorithm cannot be
    applied more than once to make the data even smaller, since random
    noise is incompressible.  The consequence for our purposes here is
    that pre-compressed data doesn’t benefit from Fossil’s zlib
    compression.

[dc]:  ./delta_format.wiki
[hf]:  https://en.wikipedia.org/wiki/Hash_function
[prn]: https://en.wikipedia.org/wiki/Pseudorandomness
[zl]:  http://www.zlib.net/


## Key Advice

If you read no further, the takeaway from the prior two points is that
you should not store already-compressed data in a Fossil repository.
You’ll defeat both of its compression methods, ballooning the Fossil
repository size.

The remainder of this article shows the consequences of ignoring this
advice. We’ll use 2D image files as our example here, but realize that
this advice also applies to many other file types:

*   **Microsoft Office**: The [XML-based document formats][oox] used
    from Office 2003 onward (`.docx`, `.xlsx`, `.pptx`, etc.) are Zip
    files containing an XML document file and several collateral files.
    The same is true of LibreOffice’s [ODF][odf] files.

*   **[Java][jcl]**: A `.jar` file is a Zip file containing JVM
    `.class` files, manifest files, and more.

*   **[Windows Installer][wi]:** An `*.msi` file is a proprietary
    database format that contains, among other things, [Microsoft
    Cabinet][cab]-compressed files, which in turn may hold Windows
    executables, which [may themselves be compressed][exc].

*   **SVG, PDF**: Many file formats are available in both compressed
    and uncompressed forms. For the same basic reason as we will
    illustrate below, you should use the uncompressed form with Fossil
    wherever practical.


[cab]: https://en.wikipedia.org/wiki/Cabinet_(file_format)
[exc]: https://en.wikipedia.org/wiki/Executable_compression
[jcl]: https://en.wikipedia.org/wiki/Java_(programming_language)
[odf]: https://en.wikipedia.org/wiki/OpenDocument
[oox]: https://en.wikipedia.org/wiki/Office_Open_XML
[wi]:  https://en.wikipedia.org/wiki/Windows_Installer



## Demonstration

The [`image-format-vs-repo-size.ipynb` file][nb] in this directory is a
[Jupyter][jp] notebook implementing the following experiment:

1.  Create an empty Fossil repository, and save its initial size.

2.  Use [ImageMagick][im] via [Wand][wp] to generate a JPEG file of a
    particular size — currently 256 px² — filled with Gaussian noise to
    make data compression difficult.

3.  Check that image into the new Fossil repo, and remember that size.

4.  Change a random pixel in the image to a random RGB value, save that
    image, check it in, and remember the new Fossil repo size.

5.  Iterate on step 4 some number of times — currently 10 — and remember
    the Fossil repo size at each step.

6.  Repeat the above steps for BMP, TIFF,² and PNG.

7.  Create a bar chart showing how the Fossil repository size changes
    with each checkin.

We chose to use Jupyter for this because it makes it easy for you to
modify the notebook to try different things.  Want to see how the
results change with a different image size?  Easy, change the `size`
value in the second cell of the notebook.  Want to try more image
formats?  You can put anything ImageMagick can recognize into the
`formats` list. Want to find the break-even point for images like those
in your own respository?  Easily done with a small amount of code.

[im]: https://www.imagemagick.org/
[jp]: https://jupyter.org/
[nb]: ./image-format-vs-repo-size.ipynb
[wp]: http://wand-py.org/


## Results

Running the notebook gives a bar chart something like³ this:

![results bar chart](./image-format-vs-repo-size.svg)

There are several points of interest in that chart:

*   The initial repository size (group "0") is the same in all four
    cases. This is the normal overhead for an empty Fossil repository,
    about 200&nbsp;kiB.

*   BMP and uncompressed TIFF are nearly identical in size for all
    checkins. A low-tech format like BMP will have a small edge in
    practice because TIFF metadata includes the option for multiple
    timestamps, UUIDs, etc., which bloat the checkin size by creating
    many small deltas.  If you don't need the advantages of TIFF, a less
    capable image file format will give smaller checkin sizes for a
    given amount of change.

*   Because both PNG and Fossil use the zlib binary data compression
    algorithm, the first checkin (group “1”) is approximately the same
    size for PNG, BMP, and TIFF.

*   The repo size balloons on the first 3 checkins due to SQLite page
    overhead and such.

*   Once we’re past that initial settling-in point, the repo size goes
    up negligibly for BMP and TIFF due to Fossil’s delta compression
    algorithm: a single-pixel change results in a very small increase in
    the Fossil repo size, as we want.  PNG and JPEG, though, show large
    increases on each checkin because this same tiny input change causes
    a large change in the computed delta.

*   Because JPEG’s lossy nature allows it to start smaller and have
    smaller size increases than than PNG, the crossover point with
    BMP/TIFF isn’t until 7-9 checkins in typical runs of this test.
    Given a choice among these four file formats and a willingness to
    use lossy image compression, a rational tradeoff is to choose JPEG
    for repositories where each image will change fewer than that number
    of times.

[mce]: https://en.wikipedia.org/wiki/Monte_Carlo_method


## Automated Recompression

Since programs that produce and consume binary-compressed data files
often make it either difficult or impossible to work with the
uncompressed form, we want an automated method for producing the
uncompressed form to make Fossil happy while still having the compressed
form to keep our content creation applications happy.  This `Makefile`
should⁴ do that for BMP, PNG, SVG, and XLSX files:

        .SUFFIXES: .bmp .png .svg .svgz

        .svgz.svg:
            gzip -dc < $< > $@

        .svg.svgz:
            gzip -9c < $< > $@

        .bmp.png:
            convert -quality 95 $< $@

        .png.bmp:
            convert $< $@

        SS_FILES := $(wildcard spreadsheet/*)


        all: $(SS_FILES) illus.svg image.bmp doc-big.pdf

        reconstitute: illus.svgz image.png
            ( cd spreadsheet ; zip -9 ../spreadsheet.xlsx) * )
            qpdf doc-big.pdf doc-small.pdf


        $(SS_FILES): spreadsheet.xlsx
            unzip $@ -d $<

        doc-big.pdf: doc-small.pdf
            qpdf --stream-data=uncompress $@ $<

This `Makefile` allows you to treat the compressed version as the
process input, but to actually check in only the changes against the
uncompressed version by typing “`make`” before “`fossil ci`”.

Because it’s based on dependency rules, only the necessary files are
generated on each `make` command.

You only have to run “`make reconstitute`” *once* after opening a fresh
Fossil checkout to produce those compressed sources. After that, you
work with the compressed files in your content creation programs.

The `Makefile` illustrates two primary strategies:


### Input and Ouput File Formats Differ by Extension

In the case of SVG and the bitmap image formats, the file name extension
differs between the cases, so we can use `make` suffix rules to get the
behavior we want.  The top half of the `Makefile` just tells `make` how
to map from `*.svg` to `*.svgz` and vice versa, and the same for `*.bmp`
to/from `*.png`.


### Same Extension

We don’t have that luxury for Excel and PDF files, for different
reasons:

*   **Excel:** Excel has no way to work with the unpacked Zip file
    contents at all, so we have to unpack it into a subdirectory, which
    is what we check into Fossil.  On making a fresh Fossil checkout, we
    have to pack that subdirectory’s contents back up into an `*.xlsx`
    file with “`make reconstitute`” so we can edit it with Excel again.

*   **PDF:** All PDF readers can display an uncompressed PDF file, but
    many PDF-*producing* programs have no option for uncompressed
    output.  Since the file name extension is the same either way, we
    treat the compressed PDF as the source to the process, yielding an
    automatically-uncompressed PDF for the benefit of Fossil.  Unlike
    with the Excel case, there is no simple “file base name to directory
    name” mapping, so we just created the `-big` to `-small` name scheme
    here.

----


## Footnotes

1.  Several other programs also do delta compression, so they’ll also be
    affected by this problem: [rsync][rs], [Unison][us], [Git][git],
    etc. When using file copying and synchronization programs *without*
    delta compression, it’s best to use the most highly-compressed file
    format you can tolerate, since they copy the whole file any time any
    bit of it changes.

2.  We're using *uncompressed* TIFF here, not [LZW][lzw]- or
    Zip-compressed TIFF, either of which would give similar results to
    PNG, which is always zlib-compressed.

3.  The raw data changes somewhat from one run to the next due to the
    use of random noise in the image to make the zlib/PNG compression
    more difficult, and the random pixel changes.  Those test design
    choices make this a [Monte Carlo experient][mce].  We’ve found that
    the overall character of the results don’t change much from one run
    to the next.

4.  The `Makefile` above is not battle-tested.  Please report bugs and
    needed extensions [on the forum][for].

[for]: https://fossil-scm.org/forum/forumpost/15e677f2c8
[git]: https://git-scm.com/
[lzw]: https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch
[rs]:  https://rsync.samba.org/
[us]:  http://www.cis.upenn.edu/~bcpierce/unison/
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































































































































































































































































































































Deleted www/image-format-vs-repo-size.svg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Created with matplotlib (http://matplotlib.org/) -->
<svg height="288pt" version="1.1" viewBox="0 0 504 288" width="504pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <style type="text/css">
*{stroke-linecap:butt;stroke-linejoin:round;}
  </style>
 </defs>
 <g id="figure_1">
  <g id="patch_1">
   <path d="M 0 288 
L 504 288 
L 504 0 
L 0 0 
z
" style="fill:#ffffff;"/>
  </g>
  <g id="axes_1">
   <g id="patch_2">
    <path d="M 63 252 
L 453.6 252 
L 453.6 34.56 
L 63 34.56 
z
" style="fill:#ffffff;"/>
   </g>
   <g id="patch_3">
    <path clip-path="url(#p60d72f5e8e)" d="M 70.939024 252 
L 77.290244 252 
L 77.290244 205.23871 
L 70.939024 205.23871 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_4">
    <path clip-path="url(#p60d72f5e8e)" d="M 102.695122 252 
L 109.046341 252 
L 109.046341 195.218433 
L 102.695122 195.218433 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_5">
    <path clip-path="url(#p60d72f5e8e)" d="M 134.45122 252 
L 140.802439 252 
L 140.802439 185.198157 
L 134.45122 185.198157 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_6">
    <path clip-path="url(#p60d72f5e8e)" d="M 166.207317 252 
L 172.558537 252 
L 172.558537 173.507834 
L 166.207317 173.507834 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_7">
    <path clip-path="url(#p60d72f5e8e)" d="M 197.963415 252 
L 204.314634 252 
L 204.314634 161.817512 
L 197.963415 161.817512 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_8">
    <path clip-path="url(#p60d72f5e8e)" d="M 229.719512 252 
L 236.070732 252 
L 236.070732 157.642396 
L 229.719512 157.642396 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_9">
    <path clip-path="url(#p60d72f5e8e)" d="M 261.47561 252 
L 267.826829 252 
L 267.826829 157.642396 
L 261.47561 157.642396 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_10">
    <path clip-path="url(#p60d72f5e8e)" d="M 293.231707 252 
L 299.582927 252 
L 299.582927 140.941935 
L 293.231707 140.941935 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_11">
    <path clip-path="url(#p60d72f5e8e)" d="M 324.987805 252 
L 331.339024 252 
L 331.339024 140.941935 
L 324.987805 140.941935 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_12">
    <path clip-path="url(#p60d72f5e8e)" d="M 356.743902 252 
L 363.095122 252 
L 363.095122 135.096774 
L 356.743902 135.096774 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_13">
    <path clip-path="url(#p60d72f5e8e)" d="M 388.5 252 
L 394.85122 252 
L 394.85122 127.581567 
L 388.5 127.581567 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_14">
    <path clip-path="url(#p60d72f5e8e)" d="M 420.256098 252 
L 426.607317 252 
L 426.607317 124.241475 
L 420.256098 124.241475 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_15">
    <path clip-path="url(#p60d72f5e8e)" d="M 77.290244 252 
L 83.641463 252 
L 83.641463 205.23871 
L 77.290244 205.23871 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_16">
    <path clip-path="url(#p60d72f5e8e)" d="M 109.046341 252 
L 115.397561 252 
L 115.397561 181.858065 
L 109.046341 181.858065 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_17">
    <path clip-path="url(#p60d72f5e8e)" d="M 140.802439 252 
L 147.153659 252 
L 147.153659 157.642396 
L 140.802439 157.642396 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_18">
    <path clip-path="url(#p60d72f5e8e)" d="M 172.558537 252 
L 178.909756 252 
L 178.909756 133.426728 
L 172.558537 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_19">
    <path clip-path="url(#p60d72f5e8e)" d="M 204.314634 252 
L 210.665854 252 
L 210.665854 133.426728 
L 204.314634 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_20">
    <path clip-path="url(#p60d72f5e8e)" d="M 236.070732 252 
L 242.421951 252 
L 242.421951 133.426728 
L 236.070732 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_21">
    <path clip-path="url(#p60d72f5e8e)" d="M 267.826829 252 
L 274.178049 252 
L 274.178049 133.426728 
L 267.826829 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_22">
    <path clip-path="url(#p60d72f5e8e)" d="M 299.582927 252 
L 305.934146 252 
L 305.934146 133.426728 
L 299.582927 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_23">
    <path clip-path="url(#p60d72f5e8e)" d="M 331.339024 252 
L 337.690244 252 
L 337.690244 133.426728 
L 331.339024 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_24">
    <path clip-path="url(#p60d72f5e8e)" d="M 363.095122 252 
L 369.446341 252 
L 369.446341 133.426728 
L 363.095122 133.426728 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_25">
    <path clip-path="url(#p60d72f5e8e)" d="M 394.85122 252 
L 401.202439 252 
L 401.202439 132.591705 
L 394.85122 132.591705 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_26">
    <path clip-path="url(#p60d72f5e8e)" d="M 426.607317 252 
L 432.958537 252 
L 432.958537 132.591705 
L 426.607317 132.591705 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_27">
    <path clip-path="url(#p60d72f5e8e)" d="M 83.641463 252 
L 89.992683 252 
L 89.992683 205.23871 
L 83.641463 205.23871 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_28">
    <path clip-path="url(#p60d72f5e8e)" d="M 115.397561 252 
L 121.74878 252 
L 121.74878 181.858065 
L 115.397561 181.858065 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_29">
    <path clip-path="url(#p60d72f5e8e)" d="M 147.153659 252 
L 153.504878 252 
L 153.504878 157.642396 
L 147.153659 157.642396 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_30">
    <path clip-path="url(#p60d72f5e8e)" d="M 178.909756 252 
L 185.260976 252 
L 185.260976 133.426728 
L 178.909756 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_31">
    <path clip-path="url(#p60d72f5e8e)" d="M 210.665854 252 
L 217.017073 252 
L 217.017073 133.426728 
L 210.665854 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_32">
    <path clip-path="url(#p60d72f5e8e)" d="M 242.421951 252 
L 248.773171 252 
L 248.773171 133.426728 
L 242.421951 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_33">
    <path clip-path="url(#p60d72f5e8e)" d="M 274.178049 252 
L 280.529268 252 
L 280.529268 133.426728 
L 274.178049 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_34">
    <path clip-path="url(#p60d72f5e8e)" d="M 305.934146 252 
L 312.285366 252 
L 312.285366 133.426728 
L 305.934146 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_35">
    <path clip-path="url(#p60d72f5e8e)" d="M 337.690244 252 
L 344.041463 252 
L 344.041463 133.426728 
L 337.690244 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_36">
    <path clip-path="url(#p60d72f5e8e)" d="M 369.446341 252 
L 375.797561 252 
L 375.797561 133.426728 
L 369.446341 133.426728 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_37">
    <path clip-path="url(#p60d72f5e8e)" d="M 401.202439 252 
L 407.553659 252 
L 407.553659 132.591705 
L 401.202439 132.591705 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_38">
    <path clip-path="url(#p60d72f5e8e)" d="M 432.958537 252 
L 439.309756 252 
L 439.309756 132.591705 
L 432.958537 132.591705 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_39">
    <path clip-path="url(#p60d72f5e8e)" d="M 89.992683 252 
L 96.343902 252 
L 96.343902 205.23871 
L 89.992683 205.23871 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_40">
    <path clip-path="url(#p60d72f5e8e)" d="M 121.74878 252 
L 128.1 252 
L 128.1 185.198157 
L 121.74878 185.198157 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_41">
    <path clip-path="url(#p60d72f5e8e)" d="M 153.504878 252 
L 159.856098 252 
L 159.856098 162.652535 
L 153.504878 162.652535 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_42">
    <path clip-path="url(#p60d72f5e8e)" d="M 185.260976 252 
L 191.612195 252 
L 191.612195 130.086636 
L 185.260976 130.086636 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_43">
    <path clip-path="url(#p60d72f5e8e)" d="M 217.017073 252 
L 223.368293 252 
L 223.368293 127.581567 
L 217.017073 127.581567 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_44">
    <path clip-path="url(#p60d72f5e8e)" d="M 248.773171 252 
L 255.12439 252 
L 255.12439 100.025806 
L 248.773171 100.025806 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_45">
    <path clip-path="url(#p60d72f5e8e)" d="M 280.529268 252 
L 286.880488 252 
L 286.880488 98.35576 
L 280.529268 98.35576 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_46">
    <path clip-path="url(#p60d72f5e8e)" d="M 312.285366 252 
L 318.636585 252 
L 318.636585 94.180645 
L 312.285366 94.180645 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_47">
    <path clip-path="url(#p60d72f5e8e)" d="M 344.041463 252 
L 350.392683 252 
L 350.392683 76.645161 
L 344.041463 76.645161 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_48">
    <path clip-path="url(#p60d72f5e8e)" d="M 375.797561 252 
L 382.14878 252 
L 382.14878 65.789862 
L 375.797561 65.789862 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_49">
    <path clip-path="url(#p60d72f5e8e)" d="M 407.553659 252 
L 413.904878 252 
L 413.904878 50.759447 
L 407.553659 50.759447 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="patch_50">
    <path clip-path="url(#p60d72f5e8e)" d="M 439.309756 252 
L 445.660976 252 
L 445.660976 44.914286 
L 439.309756 44.914286 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
   </g>
   <g id="matplotlib.axis_1">
    <g id="xtick_1">
     <g id="line2d_1">
      <defs>
       <path d="M 0 0 
L 0 3.5 
" id="me2969b5817" style="stroke:#000000;stroke-width:0.8;"/>
      </defs>
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="83.641463" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_1">
      <!-- 0 -->
      <defs>
       <path d="M 31.78125 66.40625 
Q 24.171875 66.40625 20.328125 58.90625 
Q 16.5 51.421875 16.5 36.375 
Q 16.5 21.390625 20.328125 13.890625 
Q 24.171875 6.390625 31.78125 6.390625 
Q 39.453125 6.390625 43.28125 13.890625 
Q 47.125 21.390625 47.125 36.375 
Q 47.125 51.421875 43.28125 58.90625 
Q 39.453125 66.40625 31.78125 66.40625 
z
M 31.78125 74.21875 
Q 44.046875 74.21875 50.515625 64.515625 
Q 56.984375 54.828125 56.984375 36.375 
Q 56.984375 17.96875 50.515625 8.265625 
Q 44.046875 -1.421875 31.78125 -1.421875 
Q 19.53125 -1.421875 13.0625 8.265625 
Q 6.59375 17.96875 6.59375 36.375 
Q 6.59375 54.828125 13.0625 64.515625 
Q 19.53125 74.21875 31.78125 74.21875 
z
" id="DejaVuSans-30"/>
      </defs>
      <g transform="translate(86.400838 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
      </g>
     </g>
    </g>
    <g id="xtick_2">
     <g id="line2d_2">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="115.397561" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_2">
      <!-- 1 -->
      <defs>
       <path d="M 12.40625 8.296875 
L 28.515625 8.296875 
L 28.515625 63.921875 
L 10.984375 60.40625 
L 10.984375 69.390625 
L 28.421875 72.90625 
L 38.28125 72.90625 
L 38.28125 8.296875 
L 54.390625 8.296875 
L 54.390625 0 
L 12.40625 0 
z
" id="DejaVuSans-31"/>
      </defs>
      <g transform="translate(118.156936 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-31"/>
      </g>
     </g>
    </g>
    <g id="xtick_3">
     <g id="line2d_3">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="147.153659" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_3">
      <!-- 2 -->
      <defs>
       <path d="M 19.1875 8.296875 
L 53.609375 8.296875 
L 53.609375 0 
L 7.328125 0 
L 7.328125 8.296875 
Q 12.9375 14.109375 22.625 23.890625 
Q 32.328125 33.6875 34.8125 36.53125 
Q 39.546875 41.84375 41.421875 45.53125 
Q 43.3125 49.21875 43.3125 52.78125 
Q 43.3125 58.59375 39.234375 62.25 
Q 35.15625 65.921875 28.609375 65.921875 
Q 23.96875 65.921875 18.8125 64.3125 
Q 13.671875 62.703125 7.8125 59.421875 
L 7.8125 69.390625 
Q 13.765625 71.78125 18.9375 73 
Q 24.125 74.21875 28.421875 74.21875 
Q 39.75 74.21875 46.484375 68.546875 
Q 53.21875 62.890625 53.21875 53.421875 
Q 53.21875 48.921875 51.53125 44.890625 
Q 49.859375 40.875 45.40625 35.40625 
Q 44.1875 33.984375 37.640625 27.21875 
Q 31.109375 20.453125 19.1875 8.296875 
z
" id="DejaVuSans-32"/>
      </defs>
      <g transform="translate(149.913034 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-32"/>
      </g>
     </g>
    </g>
    <g id="xtick_4">
     <g id="line2d_4">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="178.909756" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_4">
      <!-- 3 -->
      <defs>
       <path d="M 40.578125 39.3125 
Q 47.65625 37.796875 51.625 33 
Q 55.609375 28.21875 55.609375 21.1875 
Q 55.609375 10.40625 48.1875 4.484375 
Q 40.765625 -1.421875 27.09375 -1.421875 
Q 22.515625 -1.421875 17.65625 -0.515625 
Q 12.796875 0.390625 7.625 2.203125 
L 7.625 11.71875 
Q 11.71875 9.328125 16.59375 8.109375 
Q 21.484375 6.890625 26.8125 6.890625 
Q 36.078125 6.890625 40.9375 10.546875 
Q 45.796875 14.203125 45.796875 21.1875 
Q 45.796875 27.640625 41.28125 31.265625 
Q 36.765625 34.90625 28.71875 34.90625 
L 20.21875 34.90625 
L 20.21875 43.015625 
L 29.109375 43.015625 
Q 36.375 43.015625 40.234375 45.921875 
Q 44.09375 48.828125 44.09375 54.296875 
Q 44.09375 59.90625 40.109375 62.90625 
Q 36.140625 65.921875 28.71875 65.921875 
Q 24.65625 65.921875 20.015625 65.03125 
Q 15.375 64.15625 9.8125 62.3125 
L 9.8125 71.09375 
Q 15.4375 72.65625 20.34375 73.4375 
Q 25.25 74.21875 29.59375 74.21875 
Q 40.828125 74.21875 47.359375 69.109375 
Q 53.90625 64.015625 53.90625 55.328125 
Q 53.90625 49.265625 50.4375 45.09375 
Q 46.96875 40.921875 40.578125 39.3125 
z
" id="DejaVuSans-33"/>
      </defs>
      <g transform="translate(181.669131 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-33"/>
      </g>
     </g>
    </g>
    <g id="xtick_5">
     <g id="line2d_5">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="210.665854" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_5">
      <!-- 4 -->
      <defs>
       <path d="M 37.796875 64.3125 
L 12.890625 25.390625 
L 37.796875 25.390625 
z
M 35.203125 72.90625 
L 47.609375 72.90625 
L 47.609375 25.390625 
L 58.015625 25.390625 
L 58.015625 17.1875 
L 47.609375 17.1875 
L 47.609375 0 
L 37.796875 0 
L 37.796875 17.1875 
L 4.890625 17.1875 
L 4.890625 26.703125 
z
" id="DejaVuSans-34"/>
      </defs>
      <g transform="translate(213.425229 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-34"/>
      </g>
     </g>
    </g>
    <g id="xtick_6">
     <g id="line2d_6">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="242.421951" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_6">
      <!-- 5 -->
      <defs>
       <path d="M 10.796875 72.90625 
L 49.515625 72.90625 
L 49.515625 64.59375 
L 19.828125 64.59375 
L 19.828125 46.734375 
Q 21.96875 47.46875 24.109375 47.828125 
Q 26.265625 48.1875 28.421875 48.1875 
Q 40.625 48.1875 47.75 41.5 
Q 54.890625 34.8125 54.890625 23.390625 
Q 54.890625 11.625 47.5625 5.09375 
Q 40.234375 -1.421875 26.90625 -1.421875 
Q 22.3125 -1.421875 17.546875 -0.640625 
Q 12.796875 0.140625 7.71875 1.703125 
L 7.71875 11.625 
Q 12.109375 9.234375 16.796875 8.0625 
Q 21.484375 6.890625 26.703125 6.890625 
Q 35.15625 6.890625 40.078125 11.328125 
Q 45.015625 15.765625 45.015625 23.390625 
Q 45.015625 31 40.078125 35.4375 
Q 35.15625 39.890625 26.703125 39.890625 
Q 22.75 39.890625 18.8125 39.015625 
Q 14.890625 38.140625 10.796875 36.28125 
z
" id="DejaVuSans-35"/>
      </defs>
      <g transform="translate(245.181326 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-35"/>
      </g>
     </g>
    </g>
    <g id="xtick_7">
     <g id="line2d_7">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="274.178049" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_7">
      <!-- 6 -->
      <defs>
       <path d="M 33.015625 40.375 
Q 26.375 40.375 22.484375 35.828125 
Q 18.609375 31.296875 18.609375 23.390625 
Q 18.609375 15.53125 22.484375 10.953125 
Q 26.375 6.390625 33.015625 6.390625 
Q 39.65625 6.390625 43.53125 10.953125 
Q 47.40625 15.53125 47.40625 23.390625 
Q 47.40625 31.296875 43.53125 35.828125 
Q 39.65625 40.375 33.015625 40.375 
z
M 52.59375 71.296875 
L 52.59375 62.3125 
Q 48.875 64.0625 45.09375 64.984375 
Q 41.3125 65.921875 37.59375 65.921875 
Q 27.828125 65.921875 22.671875 59.328125 
Q 17.53125 52.734375 16.796875 39.40625 
Q 19.671875 43.65625 24.015625 45.921875 
Q 28.375 48.1875 33.59375 48.1875 
Q 44.578125 48.1875 50.953125 41.515625 
Q 57.328125 34.859375 57.328125 23.390625 
Q 57.328125 12.15625 50.6875 5.359375 
Q 44.046875 -1.421875 33.015625 -1.421875 
Q 20.359375 -1.421875 13.671875 8.265625 
Q 6.984375 17.96875 6.984375 36.375 
Q 6.984375 53.65625 15.1875 63.9375 
Q 23.390625 74.21875 37.203125 74.21875 
Q 40.921875 74.21875 44.703125 73.484375 
Q 48.484375 72.75 52.59375 71.296875 
z
" id="DejaVuSans-36"/>
      </defs>
      <g transform="translate(276.937424 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-36"/>
      </g>
     </g>
    </g>
    <g id="xtick_8">
     <g id="line2d_8">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="305.934146" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_8">
      <!-- 7 -->
      <defs>
       <path d="M 8.203125 72.90625 
L 55.078125 72.90625 
L 55.078125 68.703125 
L 28.609375 0 
L 18.3125 0 
L 43.21875 64.59375 
L 8.203125 64.59375 
z
" id="DejaVuSans-37"/>
      </defs>
      <g transform="translate(308.693521 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-37"/>
      </g>
     </g>
    </g>
    <g id="xtick_9">
     <g id="line2d_9">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="337.690244" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_9">
      <!-- 8 -->
      <defs>
       <path d="M 31.78125 34.625 
Q 24.75 34.625 20.71875 30.859375 
Q 16.703125 27.09375 16.703125 20.515625 
Q 16.703125 13.921875 20.71875 10.15625 
Q 24.75 6.390625 31.78125 6.390625 
Q 38.8125 6.390625 42.859375 10.171875 
Q 46.921875 13.96875 46.921875 20.515625 
Q 46.921875 27.09375 42.890625 30.859375 
Q 38.875 34.625 31.78125 34.625 
z
M 21.921875 38.8125 
Q 15.578125 40.375 12.03125 44.71875 
Q 8.5 49.078125 8.5 55.328125 
Q 8.5 64.0625 14.71875 69.140625 
Q 20.953125 74.21875 31.78125 74.21875 
Q 42.671875 74.21875 48.875 69.140625 
Q 55.078125 64.0625 55.078125 55.328125 
Q 55.078125 49.078125 51.53125 44.71875 
Q 48 40.375 41.703125 38.8125 
Q 48.828125 37.15625 52.796875 32.3125 
Q 56.78125 27.484375 56.78125 20.515625 
Q 56.78125 9.90625 50.3125 4.234375 
Q 43.84375 -1.421875 31.78125 -1.421875 
Q 19.734375 -1.421875 13.25 4.234375 
Q 6.78125 9.90625 6.78125 20.515625 
Q 6.78125 27.484375 10.78125 32.3125 
Q 14.796875 37.15625 21.921875 38.8125 
z
M 18.3125 54.390625 
Q 18.3125 48.734375 21.84375 45.5625 
Q 25.390625 42.390625 31.78125 42.390625 
Q 38.140625 42.390625 41.71875 45.5625 
Q 45.3125 48.734375 45.3125 54.390625 
Q 45.3125 60.0625 41.71875 63.234375 
Q 38.140625 66.40625 31.78125 66.40625 
Q 25.390625 66.40625 21.84375 63.234375 
Q 18.3125 60.0625 18.3125 54.390625 
z
" id="DejaVuSans-38"/>
      </defs>
      <g transform="translate(340.449619 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-38"/>
      </g>
     </g>
    </g>
    <g id="xtick_10">
     <g id="line2d_10">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="369.446341" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_10">
      <!-- 9 -->
      <defs>
       <path d="M 10.984375 1.515625 
L 10.984375 10.5 
Q 14.703125 8.734375 18.5 7.8125 
Q 22.3125 6.890625 25.984375 6.890625 
Q 35.75 6.890625 40.890625 13.453125 
Q 46.046875 20.015625 46.78125 33.40625 
Q 43.953125 29.203125 39.59375 26.953125 
Q 35.25 24.703125 29.984375 24.703125 
Q 19.046875 24.703125 12.671875 31.3125 
Q 6.296875 37.9375 6.296875 49.421875 
Q 6.296875 60.640625 12.9375 67.421875 
Q 19.578125 74.21875 30.609375 74.21875 
Q 43.265625 74.21875 49.921875 64.515625 
Q 56.59375 54.828125 56.59375 36.375 
Q 56.59375 19.140625 48.40625 8.859375 
Q 40.234375 -1.421875 26.421875 -1.421875 
Q 22.703125 -1.421875 18.890625 -0.6875 
Q 15.09375 0.046875 10.984375 1.515625 
z
M 30.609375 32.421875 
Q 37.25 32.421875 41.125 36.953125 
Q 45.015625 41.5 45.015625 49.421875 
Q 45.015625 57.28125 41.125 61.84375 
Q 37.25 66.40625 30.609375 66.40625 
Q 23.96875 66.40625 20.09375 61.84375 
Q 16.21875 57.28125 16.21875 49.421875 
Q 16.21875 41.5 20.09375 36.953125 
Q 23.96875 32.421875 30.609375 32.421875 
z
" id="DejaVuSans-39"/>
      </defs>
      <g transform="translate(372.205716 265.3625)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-39"/>
      </g>
     </g>
    </g>
    <g id="xtick_11">
     <g id="line2d_11">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="401.202439" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_11">
      <!-- 10 -->
      <g transform="translate(403.961814 271.725)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-31"/>
       <use x="63.623047" xlink:href="#DejaVuSans-30"/>
      </g>
     </g>
    </g>
    <g id="xtick_12">
     <g id="line2d_12">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="432.958537" xlink:href="#me2969b5817" y="252"/>
      </g>
     </g>
     <g id="text_12">
      <!-- 11 -->
      <g transform="translate(435.717912 271.725)rotate(-90)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-31"/>
       <use x="63.623047" xlink:href="#DejaVuSans-31"/>
      </g>
     </g>
    </g>
   </g>
   <g id="matplotlib.axis_2">
    <g id="ytick_1">
     <g id="line2d_13">
      <defs>
       <path d="M 0 0 
L -3.5 0 
" id="m266e515e7d" style="stroke:#000000;stroke-width:0.8;"/>
      </defs>
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="252"/>
      </g>
     </g>
     <g id="text_13">
      <!-- 0.0 -->
      <defs>
       <path d="M 10.6875 12.40625 
L 21 12.40625 
L 21 0 
L 10.6875 0 
z
" id="DejaVuSans-2e"/>
      </defs>
      <g transform="translate(40.096875 255.799219)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-30"/>
      </g>
     </g>
    </g>
    <g id="ytick_2">
     <g id="line2d_14">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="209.24682"/>
      </g>
     </g>
     <g id="text_14">
      <!-- 0.2 -->
      <g transform="translate(40.096875 213.046039)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-32"/>
      </g>
     </g>
    </g>
    <g id="ytick_3">
     <g id="line2d_15">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="166.493641"/>
      </g>
     </g>
     <g id="text_15">
      <!-- 0.4 -->
      <g transform="translate(40.096875 170.292859)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-34"/>
      </g>
     </g>
    </g>
    <g id="ytick_4">
     <g id="line2d_16">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="123.740461"/>
      </g>
     </g>
     <g id="text_16">
      <!-- 0.6 -->
      <g transform="translate(40.096875 127.53968)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-36"/>
      </g>
     </g>
    </g>
    <g id="ytick_5">
     <g id="line2d_17">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="80.987281"/>
      </g>
     </g>
     <g id="text_17">
      <!-- 0.8 -->
      <g transform="translate(40.096875 84.7865)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-30"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-38"/>
      </g>
     </g>
    </g>
    <g id="ytick_6">
     <g id="line2d_18">
      <g>
       <use style="stroke:#000000;stroke-width:0.8;" x="63" xlink:href="#m266e515e7d" y="38.234101"/>
      </g>
     </g>
     <g id="text_18">
      <!-- 1.0 -->
      <g transform="translate(40.096875 42.03332)scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-31"/>
       <use x="63.623047" xlink:href="#DejaVuSans-2e"/>
       <use x="95.410156" xlink:href="#DejaVuSans-30"/>
      </g>
     </g>
    </g>
   </g>
   <g id="patch_51">
    <path d="M 63 252 
L 63 34.56 
" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/>
   </g>
   <g id="patch_52">
    <path d="M 453.6 252 
L 453.6 34.56 
" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/>
   </g>
   <g id="patch_53">
    <path d="M 63 252 
L 453.6 252 
" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/>
   </g>
   <g id="patch_54">
    <path d="M 63 34.56 
L 453.6 34.56 
" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/>
   </g>
   <g id="legend_1">
    <g id="patch_55">
     <path d="M 70 101.2725 
L 125.046875 101.2725 
Q 127.046875 101.2725 127.046875 99.2725 
L 127.046875 41.56 
Q 127.046875 39.56 125.046875 39.56 
L 70 39.56 
Q 68 39.56 68 41.56 
L 68 99.2725 
Q 68 101.2725 70 101.2725 
z
" style="fill:#ffffff;opacity:0.8;stroke:#cccccc;stroke-linejoin:miter;"/>
    </g>
    <g id="patch_56">
     <path d="M 72 51.158437 
L 92 51.158437 
L 92 44.158437 
L 72 44.158437 
z
" style="fill:#3b4cc0;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
    </g>
    <g id="text_19">
     <!-- JPEG -->
     <defs>
      <path d="M 9.8125 72.90625 
L 19.671875 72.90625 
L 19.671875 5.078125 
Q 19.671875 -8.109375 14.671875 -14.0625 
Q 9.671875 -20.015625 -1.421875 -20.015625 
L -5.171875 -20.015625 
L -5.171875 -11.71875 
L -2.09375 -11.71875 
Q 4.4375 -11.71875 7.125 -8.046875 
Q 9.8125 -4.390625 9.8125 5.078125 
z
" id="DejaVuSans-4a"/>
      <path d="M 19.671875 64.796875 
L 19.671875 37.40625 
L 32.078125 37.40625 
Q 38.96875 37.40625 42.71875 40.96875 
Q 46.484375 44.53125 46.484375 51.125 
Q 46.484375 57.671875 42.71875 61.234375 
Q 38.96875 64.796875 32.078125 64.796875 
z
M 9.8125 72.90625 
L 32.078125 72.90625 
Q 44.34375 72.90625 50.609375 67.359375 
Q 56.890625 61.8125 56.890625 51.125 
Q 56.890625 40.328125 50.609375 34.8125 
Q 44.34375 29.296875 32.078125 29.296875 
L 19.671875 29.296875 
L 19.671875 0 
L 9.8125 0 
z
" id="DejaVuSans-50"/>
      <path d="M 9.8125 72.90625 
L 55.90625 72.90625 
L 55.90625 64.59375 
L 19.671875 64.59375 
L 19.671875 43.015625 
L 54.390625 43.015625 
L 54.390625 34.71875 
L 19.671875 34.71875 
L 19.671875 8.296875 
L 56.78125 8.296875 
L 56.78125 0 
L 9.8125 0 
z
" id="DejaVuSans-45"/>
      <path d="M 59.515625 10.40625 
L 59.515625 29.984375 
L 43.40625 29.984375 
L 43.40625 38.09375 
L 69.28125 38.09375 
L 69.28125 6.78125 
Q 63.578125 2.734375 56.6875 0.65625 
Q 49.8125 -1.421875 42 -1.421875 
Q 24.90625 -1.421875 15.25 8.5625 
Q 5.609375 18.5625 5.609375 36.375 
Q 5.609375 54.25 15.25 64.234375 
Q 24.90625 74.21875 42 74.21875 
Q 49.125 74.21875 55.546875 72.453125 
Q 61.96875 70.703125 67.390625 67.28125 
L 67.390625 56.78125 
Q 61.921875 61.421875 55.765625 63.765625 
Q 49.609375 66.109375 42.828125 66.109375 
Q 29.4375 66.109375 22.71875 58.640625 
Q 16.015625 51.171875 16.015625 36.375 
Q 16.015625 21.625 22.71875 14.15625 
Q 29.4375 6.6875 42.828125 6.6875 
Q 48.046875 6.6875 52.140625 7.59375 
Q 56.25 8.5 59.515625 10.40625 
z
" id="DejaVuSans-47"/>
     </defs>
     <g transform="translate(100 51.158437)scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-4a"/>
      <use x="29.492188" xlink:href="#DejaVuSans-50"/>
      <use x="89.794922" xlink:href="#DejaVuSans-45"/>
      <use x="152.978516" xlink:href="#DejaVuSans-47"/>
     </g>
    </g>
    <g id="patch_57">
     <path d="M 72 65.836562 
L 92 65.836562 
L 92 58.836562 
L 72 58.836562 
z
" style="fill:#aac7fd;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
    </g>
    <g id="text_20">
     <!-- BMP -->
     <defs>
      <path d="M 19.671875 34.8125 
L 19.671875 8.109375 
L 35.5 8.109375 
Q 43.453125 8.109375 47.28125 11.40625 
Q 51.125 14.703125 51.125 21.484375 
Q 51.125 28.328125 47.28125 31.5625 
Q 43.453125 34.8125 35.5 34.8125 
z
M 19.671875 64.796875 
L 19.671875 42.828125 
L 34.28125 42.828125 
Q 41.5 42.828125 45.03125 45.53125 
Q 48.578125 48.25 48.578125 53.8125 
Q 48.578125 59.328125 45.03125 62.0625 
Q 41.5 64.796875 34.28125 64.796875 
z
M 9.8125 72.90625 
L 35.015625 72.90625 
Q 46.296875 72.90625 52.390625 68.21875 
Q 58.5 63.53125 58.5 54.890625 
Q 58.5 48.1875 55.375 44.234375 
Q 52.25 40.28125 46.1875 39.3125 
Q 53.46875 37.75 57.5 32.78125 
Q 61.53125 27.828125 61.53125 20.40625 
Q 61.53125 10.640625 54.890625 5.3125 
Q 48.25 0 35.984375 0 
L 9.8125 0 
z
" id="DejaVuSans-42"/>
      <path d="M 9.8125 72.90625 
L 24.515625 72.90625 
L 43.109375 23.296875 
L 61.8125 72.90625 
L 76.515625 72.90625 
L 76.515625 0 
L 66.890625 0 
L 66.890625 64.015625 
L 48.09375 14.015625 
L 38.1875 14.015625 
L 19.390625 64.015625 
L 19.390625 0 
L 9.8125 0 
z
" id="DejaVuSans-4d"/>
     </defs>
     <g transform="translate(100 65.836562)scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-42"/>
      <use x="68.603516" xlink:href="#DejaVuSans-4d"/>
      <use x="154.882812" xlink:href="#DejaVuSans-50"/>
     </g>
    </g>
    <g id="patch_58">
     <path d="M 72 80.514687 
L 92 80.514687 
L 92 73.514687 
L 72 73.514687 
z
" style="fill:#f7b89c;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
    </g>
    <g id="text_21">
     <!-- TIFF -->
     <defs>
      <path d="M -0.296875 72.90625 
L 61.375 72.90625 
L 61.375 64.59375 
L 35.5 64.59375 
L 35.5 0 
L 25.59375 0 
L 25.59375 64.59375 
L -0.296875 64.59375 
z
" id="DejaVuSans-54"/>
      <path d="M 9.8125 72.90625 
L 19.671875 72.90625 
L 19.671875 0 
L 9.8125 0 
z
" id="DejaVuSans-49"/>
      <path d="M 9.8125 72.90625 
L 51.703125 72.90625 
L 51.703125 64.59375 
L 19.671875 64.59375 
L 19.671875 43.109375 
L 48.578125 43.109375 
L 48.578125 34.8125 
L 19.671875 34.8125 
L 19.671875 0 
L 9.8125 0 
z
" id="DejaVuSans-46"/>
     </defs>
     <g transform="translate(100 80.514687)scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-54"/>
      <use x="61.083984" xlink:href="#DejaVuSans-49"/>
      <use x="90.576172" xlink:href="#DejaVuSans-46"/>
      <use x="148.095703" xlink:href="#DejaVuSans-46"/>
     </g>
    </g>
    <g id="patch_59">
     <path d="M 72 95.192813 
L 92 95.192813 
L 92 88.192813 
L 72 88.192813 
z
" style="fill:#b40426;stroke:#ffffff;stroke-linejoin:miter;stroke-width:2;"/>
    </g>
    <g id="text_22">
     <!-- PNG -->
     <defs>
      <path d="M 9.8125 72.90625 
L 23.09375 72.90625 
L 55.421875 11.921875 
L 55.421875 72.90625 
L 64.984375 72.90625 
L 64.984375 0 
L 51.703125 0 
L 19.390625 60.984375 
L 19.390625 0 
L 9.8125 0 
z
" id="DejaVuSans-4e"/>
     </defs>
     <g transform="translate(100 95.192813)scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-50"/>
      <use x="60.302734" xlink:href="#DejaVuSans-4e"/>
      <use x="135.107422" xlink:href="#DejaVuSans-47"/>
     </g>
    </g>
   </g>
  </g>
 </g>
 <defs>
  <clipPath id="p60d72f5e8e">
   <rect height="217.44" width="390.6" x="63" y="34.56"/>
  </clipPath>
 </defs>
</svg>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Changes to www/makefile.wiki.

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
all of the makefiles for all targets will be rebuild.

There is an option code verification step implemented using

  15.  [/file/src/codecheck1.c | codecheck1.c]

This file implements a small utility program ("codecheck1")
that scans other Fossil source files looking for errors in printf-style
format strings.
The codecheck1 utility detects missing or surplus arguments on
printf-like functions and dangerous uses of "%s" that might
permit SQL injection or cross-site scripting attacks.  This code
check step is run automatically on each build of Fossil, and can
also be run separately by typing "make codecheck".  Note that the
built-in printf format checking of GCC does not function for Fossil
since Fossil implements its own printf (in the
[/file/src/printf.c | printf.c] source file) that includes special







|

|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
all of the makefiles for all targets will be rebuild.

There is an option code verification step implemented using

  15.  [/file/src/codecheck1.c | codecheck1.c]

This file implements a small utility program ("codecheck1")
that scans other Fossil source files looking for errors in printf-style 
format strings.
The codecheck1 utility detects missing or surplus arguments on 
printf-like functions and dangerous uses of "%s" that might
permit SQL injection or cross-site scripting attacks.  This code
check step is run automatically on each build of Fossil, and can
also be run separately by typing "make codecheck".  Note that the
built-in printf format checking of GCC does not function for Fossil
since Fossil implements its own printf (in the
[/file/src/printf.c | printf.c] source file) that includes special

Deleted www/mirrortogithub.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# How To Mirror A Fossil Repository On GitHub

Beginning with Fossil version 2.9, you can mirror a Fossil-based
project on GitHub by following these steps:

<ol>
<li><p>Create an account on GitHub if you do not have one already.  Log
    into that account.

<li><p>Create a new project.  GitHub will ask you if you want to prepopulate
    your project with various things like a README file.  Answer "no" to
    everything.  You want a completely blank project.  GitHub will then
    supply you with a URL for your project that will look something
    like this:

<blockquote>
https://github.com/username/project.git
</blockquote>

<li><p>Back on your workstation, move to a checkout for your Fossil
    project and type:

<blockquote>
<pre>$ fossil git export /path/to/git/repo --autopush \
  https://<font color="orange">username</font>:<font color="red">password</font>@github.com/username/project.git</pre>
</blockquote>

<p>   In place of the <code>/path/to...</code> argument above, put in
      some directory name that is <i>outside</i> of your Fossil checkout. If
      you keep multiple Fossil checkouts in a directory of their own,
      consider using <code>../git-mirror</code> to place the Git export
      mirror alongside them, for example.  Fossil will create this
      directory if necessary.  This directory will become a Git
      repository that holds a translation of your Fossil repository.

<p>   The <code>--autopush</code> option tells Fossil that you want to
      push the Git translation up to GitHub every time it is updated.
      
<p>   The URL parameter is the same as the one GitHub gave you, but with
      your GitHub <font color="orange">username</font> and <font
      color="red">password</font> added.
      
<p>   If your GitHub account uses two-factor authentication (2FA), you
      will have to <a href="https://github.com/settings/tokens">generate
      a personal access token</a> and use that in place of your actual
      password in the URL. This token should have “repo” scope enabled,
      only.

<p>   You can also run the command above outside of any open checkout of
      your project by supplying the “<code>-R&nbsp;repository</code>”
      option.

<li><p>Get some coffee.  Depending on the size of your project, the
       command above can run for several minutes.

<li><p>And you are done!  Assuming everything worked, your project is now
    mirrored on GitHub.

<li><p>Whenever you update your project, simply run this command to update
    the mirror:

<blockquote>
<pre>$ fossil git export</pre>
</blockquote>


<p>   Unlike with the first time you ran that command, you don’t need
      the remaining arguments, because Fossil remembers those things.
      Subsequent mirror updates should happen in a second or less.
</ol>

## Notes:

  *  The mirroring is one-way.  If you check in changes on GitHub, those
     changes will not be reabsorbed by Fossil.  There are technical problems
     that make a two-way mirror all but impossible.

     This also means that you cannot accept pull requests on GitHub.

  *  The "`fossil git export`" command creates subprocesses that run "`git`"
     commands, so you must have Git installed on your machine for any
     of this to work.

  *  The Git repository will have an extra unmanaged top-level directory named
     "`.mirror_state`" that contains one or more files.  Those files are
     used to store the intermediate state of the translation so that
     subsequent invocations of "`fossil git export`" will know where you
     left off the last time and what new content needs to be moved over into
     Git.  Be careful not to mess with the `.mirror_state` directory or
     any of its contents.  Do not put those files under Git management.  Do
     not edit or delete them.

  *  Only check-ins and simple tags are translated to Git.  Git does not
     support wiki or tickets or unversioned content or any of the other
     features of Fossil that make it so convenient to use, so those other
     elements cannot be mirrored in Git.

  *  In Git, all tags must be unique.  If your Fossil repository has the
     same tag on two or more check-ins, the tag will only be preserved on
     the chronologically newest check-in.

## Example GitHub Mirrors

As of this writing (2019-03-16) Fossil’s own repository is mirrored
on GitHub at:

>
<https://github.com/drhsqlite/fossil-mirror>

In addition, an experimental SQLite mirror is available:

>
<https://github.com/drhsqlite/sqlite-mirror>

The Fossil source repositories for both of these mirrors are at
<https://www2.fossil-scm.org/fossil> and <https://www2.sqlite.org/src>,
respectively.  On that machine, there is a cron job that runs at
17 minutes after the hour, every hour that does:

>
    /usr/bin/fossil sync -u -R /home/www/fossil/fossil.fossil
    /usr/bin/fossil sync -R /home/www/fossil/sqlite.fossil
    /usr/bin/fossil git export -R /home/www/fossil/fossil.fossil
    /usr/bin/fossil git export -R /home/www/fossil/sqlite.fossil

The initial two "sync" commands pull in changes from the primary
Fossil repositores for Fossil and SQLite.  The last two lines
export the changes to Git and push the results up to GitHub.
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































































































































































































































































Changes to www/mkindex.tcl.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  grep.md {Fossil grep vs POSIX grep}
  hacker-howto.wiki {Hacker How-To}
  hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
  /help {Lists of Commands and Webpages}
  hints.wiki {Fossil Tips And Usage Hints}
  index.wiki {Home Page}
  inout.wiki {Import And Export To And From Git}
  image-format-vs-repo-size.md {Image Format vs Fossil Repo Size}
  makefile.wiki {The Fossil Build Process}
  mirrortogithub.md {How To Mirror A Fossil Repository On GitHub}
  /md_rules {Markdown Formatting Rules}
  newrepo.wiki {How To Create A New Fossil Repository}
  password.wiki {Password Management And Authentication}
  pop.wiki {Principles Of Operation}
  private.wiki {Creating, Syncing, and Deleting Private Branches}
  qandc.wiki {Questions And Criticisms}
  quickstart.wiki {Fossil Quick Start Guide}
................................................................................
  sync.wiki {The Fossil Sync Protocol}
  tech_overview.wiki {A Technical Overview Of The Design And Implementation
                      Of Fossil}
  tech_overview.wiki {SQLite Databases Used By Fossil}
  th1.md {The TH1 Scripting Language}
  tickets.wiki {The Fossil Ticket System}
  theory1.wiki {Thoughts On The Design Of The Fossil DVCS}
  tls-nginx.md {Proxying Fossil via HTTPS with nginx}
  unvers.wiki {Unversioned Files}
  webpage-ex.md {Webpage Examples}
  webui.wiki {The Fossil Web Interface}
  whyusefossil.wiki {Why You Should Use Fossil}
  whyusefossil.wiki {Benefits Of Version Control}
  wikitheory.wiki {Wiki In Fossil}
  /wiki_rules {Wiki Formatting Rules}







<

<







 







<







48
49
50
51
52
53
54

55

56
57
58
59
60
61
62
..
76
77
78
79
80
81
82

83
84
85
86
87
88
89
  grep.md {Fossil grep vs POSIX grep}
  hacker-howto.wiki {Hacker How-To}
  hashpolicy.wiki {Hash Policy: Choosing Between SHA1 and SHA3-256}
  /help {Lists of Commands and Webpages}
  hints.wiki {Fossil Tips And Usage Hints}
  index.wiki {Home Page}
  inout.wiki {Import And Export To And From Git}

  makefile.wiki {The Fossil Build Process}

  /md_rules {Markdown Formatting Rules}
  newrepo.wiki {How To Create A New Fossil Repository}
  password.wiki {Password Management And Authentication}
  pop.wiki {Principles Of Operation}
  private.wiki {Creating, Syncing, and Deleting Private Branches}
  qandc.wiki {Questions And Criticisms}
  quickstart.wiki {Fossil Quick Start Guide}
................................................................................
  sync.wiki {The Fossil Sync Protocol}
  tech_overview.wiki {A Technical Overview Of The Design And Implementation
                      Of Fossil}
  tech_overview.wiki {SQLite Databases Used By Fossil}
  th1.md {The TH1 Scripting Language}
  tickets.wiki {The Fossil Ticket System}
  theory1.wiki {Thoughts On The Design Of The Fossil DVCS}

  unvers.wiki {Unversioned Files}
  webpage-ex.md {Webpage Examples}
  webui.wiki {The Fossil Web Interface}
  whyusefossil.wiki {Why You Should Use Fossil}
  whyusefossil.wiki {Benefits Of Version Control}
  wikitheory.wiki {Wiki In Fossil}
  /wiki_rules {Wiki Formatting Rules}

Changes to www/permutedindex.html.

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
<li><a href="adding_code.wiki">Features To Fossil &mdash; Adding New</a></li>
<li><a href="fileformat.wiki">File Format &mdash; Fossil</a></li>
<li><a href="globs.md"><b>File Name Glob Patterns</b></a></li>
<li><a href="unvers.wiki">Files &mdash; Unversioned</a></li>
<li><a href="branching.wiki">Forking, Merging, and Tagging &mdash; Branching,</a></li>
<li><a href="delta_format.wiki">Format &mdash; Fossil Delta</a></li>
<li><a href="fileformat.wiki">Format &mdash; Fossil File</a></li>
<li><a href="image-format-vs-repo-size.md">Format vs Fossil Repo Size &mdash; Image</a></li>
<li><a href="../../../md_rules">Formatting Rules &mdash; Markdown</a></li>
<li><a href="../../../wiki_rules">Formatting Rules &mdash; Wiki</a></li>
<li><a href="forum.wiki">Forums &mdash; Fossil</a></li>
<li><a href="blockchain.md"><b>Fossil As Blockchain</b></a></li>
<li><a href="changes.wiki"><b>Fossil Changelog</b></a></li>
<li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li>
<li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li>
................................................................................
<li><a href="fossil-v-git.wiki"><b>Fossil Versus Git</b></a></li>
<li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are Saying About</a></li>
<li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li>
<li><a href="quotes.wiki">General &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
<li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
<li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
<li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>
<li><a href="mirrortogithub.md">GitHub &mdash; How To Mirror A Fossil Repository On</a></li>
<li><a href="globs.md">Glob Patterns &mdash; File Name</a></li>
<li><a href="env-opts.md">Global Options &mdash; Environment Variables and</a></li>
<li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
<li><a href="grep.md">grep &mdash; Fossil grep vs POSIX</a></li>
<li><a href="grep.md">grep vs POSIX grep &mdash; Fossil</a></li>
<li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
<li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
................................................................................
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
<li><a href="index.wiki"><b>Home Page</b></a></li>
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
<li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li>
<li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
<li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li>
<li><a href="mirrortogithub.md"><b>How To Mirror A Fossil Repository On GitHub</b></a></li>
<li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li>
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>
<li><a href="tls-nginx.md">HTTPS with nginx &mdash; Proxying Fossil via</a></li>
<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>
<li><a href="image-format-vs-repo-size.md"><b>Image Format vs Fossil Repo Size</b></a></li>
<li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
<li><a href="inout.wiki"><b>Import And Export To And From Git</b></a></li>
<li><a href="build.wiki">Installing Fossil &mdash; Compiling and</a></li>
<li><a href="fossil-from-msvc.wiki"><b>Integrating Fossil in the Microsoft Express 2010 IDE</b></a></li>
<li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
<li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
<li><a href="th1.md">Language &mdash; The TH1 Scripting</a></li>
................................................................................
<li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
<li><a href="../../../sitemap">Map &mdash; Site</a></li>
<li><a href="../../../md_rules"><b>Markdown Formatting Rules</b></a></li>
<li><a href="backoffice.md">mechanism of Fossil &mdash; The Backoffice</a></li>
<li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
<li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE &mdash; Integrating Fossil in the</a></li>
<li><a href="fiveminutes.wiki">Minutes as a Single User &mdash; Up and Running in 5</a></li>
<li><a href="mirrortogithub.md">Mirror A Fossil Repository On GitHub &mdash; How To</a></li>
<li><a href="globs.md">Name Glob Patterns &mdash; File</a></li>
<li><a href="checkin_names.wiki">Names &mdash; Check-in And Version</a></li>
<li><a href="adding_code.wiki">New Features To Fossil &mdash; Adding</a></li>
<li><a href="newrepo.wiki">New Fossil Repository &mdash; How To Create A</a></li>
<li><a href="tls-nginx.md">nginx &mdash; Proxying Fossil via HTTPS with</a></li>
<li><a href="alerts.md">Notifications &mdash; Email Alerts And</a></li>
<li><a href="foss-cklist.wiki">Open-Source Projects &mdash; Checklist For Successful</a></li>
<li><a href="pop.wiki">Operation &mdash; Principles Of</a></li>
<li><a href="env-opts.md">Options &mdash; Environment Variables and Global</a></li>
<li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &mdash; A Technical</a></li>
<li><a href="index.wiki">Page &mdash; Home</a></li>
<li><a href="aboutdownload.wiki">Page Works &mdash; How The Download</a></li>
................................................................................
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
<li><a href="embeddeddoc.wiki">Project Documentation &mdash; Embedded</a></li>
<li><a href="foss-cklist.wiki">Projects &mdash; Checklist For Successful Open-Source</a></li>
<li><a href="childprojects.wiki">Projects &mdash; Child</a></li>
<li><a href="sync.wiki">Protocol &mdash; The Fossil Sync</a></li>
<li><a href="tls-nginx.md"><b>Proxying Fossil via HTTPS with nginx</b></a></li>
<li><a href="faq.wiki">Questions &mdash; Frequently Asked</a></li>
<li><a href="qandc.wiki"><b>Questions And Criticisms</b></a></li>
<li><a href="quickstart.wiki">Quick Start Guide &mdash; Fossil</a></li>
<li><a href="quotes.wiki"><b>Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</b></a></li>
<li><a href="image-format-vs-repo-size.md">Repo Size &mdash; Image Format vs Fossil</a></li>
<li><a href="selfhost.wiki">Repositories &mdash; Fossil Self Hosting</a></li>
<li><a href="encryptedrepos.wiki">Repositories &mdash; How To Use Encrypted</a></li>
<li><a href="newrepo.wiki">Repository &mdash; How To Create A New Fossil</a></li>
<li><a href="selfcheck.wiki">Repository Integrity Self Checks &mdash; Fossil</a></li>
<li><a href="mirrortogithub.md">Repository On GitHub &mdash; How To Mirror A Fossil</a></li>
<li><a href="reviews.wiki"><b>Reviews</b></a></li>
<li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
<li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
<li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Up and</a></li>
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
................................................................................
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
<li><a href="admin-v-setup.md">Setup and Admin User Capabilities &mdash; The Differences Between the</a></li>
<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
<li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
<li><a href="fiveminutes.wiki">Single User &mdash; Up and Running in 5 Minutes as a</a></li>
<li><a href="../../../sitemap"><b>Site Map</b></a></li>
<li><a href="image-format-vs-repo-size.md">Size &mdash; Image Format vs Fossil Repo</a></li>
<li><a href="customskin.md">Skins &mdash; Custom</a></li>
<li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li>
<li><a href="antibot.wiki">Spiders and Bots &mdash; Defense against</a></li>
<li><a href="tech_overview.wiki"><b>SQLite Databases Used By Fossil</b></a></li>
<li><a href="ssl.wiki">SSL with Fossil &mdash; Using</a></li>
<li><a href="quickstart.wiki">Start Guide &mdash; Fossil Quick</a></li>
<li><a href="stats.wiki">Statistics &mdash; Performance</a></li>
................................................................................
<li><a href="fiveminutes.wiki">User &mdash; Up and Running in 5 Minutes as a Single</a></li>
<li><a href="admin-v-setup.md">User Capabilities &mdash; The Differences Between the Setup and Admin</a></li>
<li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li>
<li><a href="env-opts.md">Variables and Global Options &mdash; Environment</a></li>
<li><a href="whyusefossil.wiki">Version Control &mdash; Benefits Of</a></li>
<li><a href="checkin_names.wiki">Version Names &mdash; Check-in And</a></li>
<li><a href="fossil-v-git.wiki">Versus Git &mdash; Fossil</a></li>
<li><a href="tls-nginx.md">via HTTPS with nginx &mdash; Proxying Fossil</a></li>
<li><a href="image-format-vs-repo-size.md">vs Fossil Repo Size &mdash; Image Format</a></li>
<li><a href="grep.md">vs POSIX grep &mdash; Fossil grep</a></li>
<li><a href="webui.wiki">Web Interface &mdash; The Fossil</a></li>
<li><a href="customskin.md">Web Pages &mdash; Theming: Customizing The Appearance of</a></li>
<li><a href="webpage-ex.md"><b>Webpage Examples</b></a></li>
<li><a href="../../../help">Webpages &mdash; Lists of Commands and</a></li>
<li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes:</a></li>
<li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li>
<li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li>
<li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li>
<li><a href="aboutdownload.wiki">Works &mdash; How The Download Page</a></li>
<li><a href="aboutcgi.wiki">Works In Fossil &mdash; How CGI</a></li>
<li><a href="whyusefossil.wiki">You Should Use Fossil &mdash; Why</a></li>
</ul></div>







<







 







<







 







<


<

<







 







<




<







 







<




<




<







 







<







 







<
<













98
99
100
101
102
103
104

105
106
107
108
109
110
111
...
121
122
123
124
125
126
127

128
129
130
131
132
133
134
...
138
139
140
141
142
143
144

145
146

147

148
149
150
151
152
153
154
...
157
158
159
160
161
162
163

164
165
166
167

168
169
170
171
172
173
174
...
184
185
186
187
188
189
190

191
192
193
194

195
196
197
198

199
200
201
202
203
204
205
...
208
209
210
211
212
213
214

215
216
217
218
219
220
221
...
251
252
253
254
255
256
257


258
259
260
261
262
263
264
265
266
267
268
269
270
<li><a href="adding_code.wiki">Features To Fossil &mdash; Adding New</a></li>
<li><a href="fileformat.wiki">File Format &mdash; Fossil</a></li>
<li><a href="globs.md"><b>File Name Glob Patterns</b></a></li>
<li><a href="unvers.wiki">Files &mdash; Unversioned</a></li>
<li><a href="branching.wiki">Forking, Merging, and Tagging &mdash; Branching,</a></li>
<li><a href="delta_format.wiki">Format &mdash; Fossil Delta</a></li>
<li><a href="fileformat.wiki">Format &mdash; Fossil File</a></li>

<li><a href="../../../md_rules">Formatting Rules &mdash; Markdown</a></li>
<li><a href="../../../wiki_rules">Formatting Rules &mdash; Wiki</a></li>
<li><a href="forum.wiki">Forums &mdash; Fossil</a></li>
<li><a href="blockchain.md"><b>Fossil As Blockchain</b></a></li>
<li><a href="changes.wiki"><b>Fossil Changelog</b></a></li>
<li><a href="concepts.wiki"><b>Fossil Core Concepts</b></a></li>
<li><a href="delta_encoder_algorithm.wiki"><b>Fossil Delta Encoding Algorithm</b></a></li>
................................................................................
<li><a href="fossil-v-git.wiki"><b>Fossil Versus Git</b></a></li>
<li><a href="quotes.wiki">Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are Saying About</a></li>
<li><a href="faq.wiki"><b>Frequently Asked Questions</b></a></li>
<li><a href="quotes.wiki">General &mdash; Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li>
<li><a href="fossil-v-git.wiki">Git &mdash; Fossil Versus</a></li>
<li><a href="inout.wiki">Git &mdash; Import And Export To And From</a></li>
<li><a href="quotes.wiki">Git, and DVCSes in General &mdash; Quotes: What People Are Saying About Fossil,</a></li>

<li><a href="globs.md">Glob Patterns &mdash; File Name</a></li>
<li><a href="env-opts.md">Global Options &mdash; Environment Variables and</a></li>
<li><a href="customgraph.md">Graph &mdash; Theming: Customizing the Timeline</a></li>
<li><a href="grep.md">grep &mdash; Fossil grep vs POSIX</a></li>
<li><a href="grep.md">grep vs POSIX grep &mdash; Fossil</a></li>
<li><a href="quickstart.wiki">Guide &mdash; Fossil Quick Start</a></li>
<li><a href="style.wiki">Guidelines &mdash; Source Code Style</a></li>
................................................................................
<li><a href="hints.wiki">Hints &mdash; Fossil Tips And Usage</a></li>
<li><a href="index.wiki"><b>Home Page</b></a></li>
<li><a href="selfhost.wiki">Hosting Repositories &mdash; Fossil Self</a></li>
<li><a href="aboutcgi.wiki"><b>How CGI Works In Fossil</b></a></li>
<li><a href="aboutdownload.wiki"><b>How The Download Page Works</b></a></li>
<li><a href="server.wiki"><b>How To Configure A Fossil Server</b></a></li>
<li><a href="newrepo.wiki"><b>How To Create A New Fossil Repository</b></a></li>

<li><a href="encryptedrepos.wiki"><b>How To Use Encrypted Repositories</b></a></li>
<li><a href="hacker-howto.wiki">How-To &mdash; Hacker</a></li>

<li><a href="fossil-from-msvc.wiki">IDE &mdash; Integrating Fossil in the Microsoft Express 2010</a></li>

<li><a href="tech_overview.wiki">Implementation Of Fossil &mdash; A Technical Overview Of The Design And</a></li>
<li><a href="inout.wiki"><b>Import And Export To And From Git</b></a></li>
<li><a href="build.wiki">Installing Fossil &mdash; Compiling and</a></li>
<li><a href="fossil-from-msvc.wiki"><b>Integrating Fossil in the Microsoft Express 2010 IDE</b></a></li>
<li><a href="selfcheck.wiki">Integrity Self Checks &mdash; Fossil Repository</a></li>
<li><a href="webui.wiki">Interface &mdash; The Fossil Web</a></li>
<li><a href="th1.md">Language &mdash; The TH1 Scripting</a></li>
................................................................................
<li><a href="password.wiki">Management And Authentication &mdash; Password</a></li>
<li><a href="../../../sitemap">Map &mdash; Site</a></li>
<li><a href="../../../md_rules"><b>Markdown Formatting Rules</b></a></li>
<li><a href="backoffice.md">mechanism of Fossil &mdash; The Backoffice</a></li>
<li><a href="branching.wiki">Merging, and Tagging &mdash; Branching, Forking,</a></li>
<li><a href="fossil-from-msvc.wiki">Microsoft Express 2010 IDE &mdash; Integrating Fossil in the</a></li>
<li><a href="fiveminutes.wiki">Minutes as a Single User &mdash; Up and Running in 5</a></li>

<li><a href="globs.md">Name Glob Patterns &mdash; File</a></li>
<li><a href="checkin_names.wiki">Names &mdash; Check-in And Version</a></li>
<li><a href="adding_code.wiki">New Features To Fossil &mdash; Adding</a></li>
<li><a href="newrepo.wiki">New Fossil Repository &mdash; How To Create A</a></li>

<li><a href="alerts.md">Notifications &mdash; Email Alerts And</a></li>
<li><a href="foss-cklist.wiki">Open-Source Projects &mdash; Checklist For Successful</a></li>
<li><a href="pop.wiki">Operation &mdash; Principles Of</a></li>
<li><a href="env-opts.md">Options &mdash; Environment Variables and Global</a></li>
<li><a href="tech_overview.wiki">Overview Of The Design And Implementation Of Fossil &mdash; A Technical</a></li>
<li><a href="index.wiki">Page &mdash; Home</a></li>
<li><a href="aboutdownload.wiki">Page Works &mdash; How The Download</a></li>
................................................................................
<li><a href="private.wiki">Private Branches &mdash; Creating, Syncing, and Deleting</a></li>
<li><a href="makefile.wiki">Process &mdash; The Fossil Build</a></li>
<li><a href="contribute.wiki">Project &mdash; Contributing Code or Documentation To The Fossil</a></li>
<li><a href="embeddeddoc.wiki">Project Documentation &mdash; Embedded</a></li>
<li><a href="foss-cklist.wiki">Projects &mdash; Checklist For Successful Open-Source</a></li>
<li><a href="childprojects.wiki">Projects &mdash; Child</a></li>
<li><a href="sync.wiki">Protocol &mdash; The Fossil Sync</a></li>

<li><a href="faq.wiki">Questions &mdash; Frequently Asked</a></li>
<li><a href="qandc.wiki"><b>Questions And Criticisms</b></a></li>
<li><a href="quickstart.wiki">Quick Start Guide &mdash; Fossil</a></li>
<li><a href="quotes.wiki"><b>Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</b></a></li>

<li><a href="selfhost.wiki">Repositories &mdash; Fossil Self Hosting</a></li>
<li><a href="encryptedrepos.wiki">Repositories &mdash; How To Use Encrypted</a></li>
<li><a href="newrepo.wiki">Repository &mdash; How To Create A New Fossil</a></li>
<li><a href="selfcheck.wiki">Repository Integrity Self Checks &mdash; Fossil</a></li>

<li><a href="reviews.wiki"><b>Reviews</b></a></li>
<li><a href="../../../md_rules">Rules &mdash; Markdown Formatting</a></li>
<li><a href="../../../wiki_rules">Rules &mdash; Wiki Formatting</a></li>
<li><a href="fiveminutes.wiki">Running in 5 Minutes as a Single User &mdash; Up and</a></li>
<li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General &mdash; Quotes: What People Are</a></li>
<li><a href="th1.md">Scripting Language &mdash; The TH1</a></li>
<li><a href="selfcheck.wiki">Self Checks &mdash; Fossil Repository Integrity</a></li>
................................................................................
<li><a href="settings.wiki">Settings &mdash; Fossil</a></li>
<li><a href="admin-v-setup.md">Setup and Admin User Capabilities &mdash; The Differences Between the</a></li>
<li><a href="hashpolicy.wiki">SHA1 and SHA3-256 &mdash; Hash Policy: Choosing Between</a></li>
<li><a href="hashpolicy.wiki">SHA3-256 &mdash; Hash Policy: Choosing Between SHA1 and</a></li>
<li><a href="shunning.wiki"><b>Shunning: Deleting Content From Fossil</b></a></li>
<li><a href="fiveminutes.wiki">Single User &mdash; Up and Running in 5 Minutes as a</a></li>
<li><a href="../../../sitemap"><b>Site Map</b></a></li>

<li><a href="customskin.md">Skins &mdash; Custom</a></li>
<li><a href="style.wiki"><b>Source Code Style Guidelines</b></a></li>
<li><a href="antibot.wiki">Spiders and Bots &mdash; Defense against</a></li>
<li><a href="tech_overview.wiki"><b>SQLite Databases Used By Fossil</b></a></li>
<li><a href="ssl.wiki">SSL with Fossil &mdash; Using</a></li>
<li><a href="quickstart.wiki">Start Guide &mdash; Fossil Quick</a></li>
<li><a href="stats.wiki">Statistics &mdash; Performance</a></li>
................................................................................
<li><a href="fiveminutes.wiki">User &mdash; Up and Running in 5 Minutes as a Single</a></li>
<li><a href="admin-v-setup.md">User Capabilities &mdash; The Differences Between the Setup and Admin</a></li>
<li><a href="ssl.wiki"><b>Using SSL with Fossil</b></a></li>
<li><a href="env-opts.md">Variables and Global Options &mdash; Environment</a></li>
<li><a href="whyusefossil.wiki">Version Control &mdash; Benefits Of</a></li>
<li><a href="checkin_names.wiki">Version Names &mdash; Check-in And</a></li>
<li><a href="fossil-v-git.wiki">Versus Git &mdash; Fossil</a></li>


<li><a href="grep.md">vs POSIX grep &mdash; Fossil grep</a></li>
<li><a href="webui.wiki">Web Interface &mdash; The Fossil</a></li>
<li><a href="customskin.md">Web Pages &mdash; Theming: Customizing The Appearance of</a></li>
<li><a href="webpage-ex.md"><b>Webpage Examples</b></a></li>
<li><a href="../../../help">Webpages &mdash; Lists of Commands and</a></li>
<li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General &mdash; Quotes:</a></li>
<li><a href="whyusefossil.wiki"><b>Why You Should Use Fossil</b></a></li>
<li><a href="../../../wiki_rules"><b>Wiki Formatting Rules</b></a></li>
<li><a href="wikitheory.wiki"><b>Wiki In Fossil</b></a></li>
<li><a href="aboutdownload.wiki">Works &mdash; How The Download Page</a></li>
<li><a href="aboutcgi.wiki">Works In Fossil &mdash; How CGI</a></li>
<li><a href="whyusefossil.wiki">You Should Use Fossil &mdash; Why</a></li>
</ul></div>

Changes to www/server.wiki.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65




66
67


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92



93
94

95
96
97

98
99
100
101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

157
158
159


160
161
162
163
164


165
166
167





















168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188


189
190
191
192
193
194
195

196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

219

220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236


237
238
239


240
241
242

243
244

245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270


271
272
273
274


275
276
277
278
279
280
281
282
283
284
285
286
287
288

289












290
291
292
293





294
295
296
297
298

299
300
301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341

342
343
344
345
346
347
348
349

350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
386
<title>How To Configure A Fossil Server</title>

<h2>Introduction</h2>

<blockquote>
A server is not necessary to use Fossil, but a server does help in collaborating with
peers.  A Fossil server also works well as a complete website for a project.
For example, the complete [https://www.fossil-scm.org/] website, including the
page you are now reading,
is just a Fossil server displaying the content of the
self-hosting repository for Fossil.

This article is a guide for setting up your own Fossil server.

See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
information on the underlying CGI technology.
See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
wire protocol used for client/server communication.
</blockquote>

<h2>Overview</h2>

<blockquote>
There are basically four ways to set up a Fossil server:

<ol>
  <li>A stand-alone server
  <li>Using inetd, xinetd, or stunnel
  <li>CGI
  <li>SCGI (a.k.a. SimpleCGI)
</ol>

Each of these can serve either a single repository, or a directory hierarchy
containing many repositories with names ending in ".fossil".
</blockquote>


<h2 id="standalone">Standalone server</h2>

<blockquote>
The easiest way to set up a Fossil server is to use either the
[/help/server|server] or the [/help/ui|ui] commands:

<ul>
  <li><b>fossil server</b> <i>REPOSITORY</i>
  <li><b>fossil ui</b> <i>REPOSITORY</i>
</ul>


The <i>REPOSITORY</i> argument is either the name of the repository file, or
a directory containing many repositories named <tt>*.fossil</tt>.
Both of these commands start a Fossil server, usually on TCP port 8080, though
a higher numbered port might also be used if 8080 is already occupied.  You can
access these using URLs of the form <b>http://localhost:8080/</b>, or if
<i>REPOSITORY</i> is a directory, URLs of the form
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
name of the repository file without the ".fossil" suffix.

There are several key differences between "ui" and "server":

<ul>
  <li>"ui" always binds the server to the loopback IP address
      (127.0.0.1) so that it cannot serve to other machines.
  <li>anyone who visits this URL is treated as the all-powerful Setup
      user, which is why the first difference exists.
  <li>"ui" launches a local web browser pointed at this URL.




</ul>



You can omit the <i>REPOSITORY</i> argument if you run one of the above
commands from within a Fossil checkout directory to serve that
repository:

<blockquote><pre>
$ fossil ui          # or...
$ fossil serve
</pre></blockquote>

Note that you can abbreviate Fossil sub-commands, as long as they are
unambiguous. "<tt>server</tt>" can currently be as short as
"<tt>ser</tt>".

As a more complicated example, you can serve a directory containing
multiple <tt>*.fossil</tt> files like so:

<blockquote><pre>
$ fossil server --port 9000 --repolist /path/to/repo/dir
</pre></blockquote>

There is an [/file/tools/fslsrv | example script] in the Fossil
distribution that wraps <tt>fossil server</tt> to produce more
complicated effects. Feel free to take it, study it, and modify it to
suit your local needs.




See the [/help/server|online documentation] for more information on the
options and arguments you can give to these commands.

</blockquote>



<h2 id="inetd">Fossil as an inetd/xinetd service</h2>

<blockquote>


A Fossil server can be launched on-demand by inetd or xinetd using
the [/help/http|fossil http] command. To launch Fossil from inetd, modify
your inetd configuration file (typically "/etc/inetd.conf") to contain a
line something like this:

<blockquote>
<pre>
80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil
</pre>
</blockquote>

In this example, you are telling "inetd" that when an incoming connection
appears on TCP port "80", that it should launch the binary "/usr/bin/fossil"
program with the arguments shown.
Obviously you will
need to modify the pathnames for your particular setup.
The final argument is either the name of the fossil repository to be served,
or a directory containing multiple repositories.


If you use a non-standard TCP port on
systems where the port-specification must be a symbolic name and cannot be
numeric, add the desired name and port to /etc/services.  For example, if
you want your Fossil server running on TCP port 12345 instead of 80, you
will need to add:

<blockquote>
<pre>
fossil          12345/tcp  #fossil server
</pre>
</blockquote>

and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
case you use FreeBSD.



If your system is running xinetd, then the configuration is likely to be
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
An xinetd configuration file will appear like this:

<blockquote>
<pre>
service http
{
  port = 80
  socket_type = stream
  wait = no
  user = root
  server = /usr/bin/fossil
  server_args = http /home/fossil/repos/
}
</pre>
</blockquote>


The xinetd example above has Fossil configured to serve multiple
repositories, contained under the "/home/fossil/repos/" directory.



In both cases notice that Fossil was launched as root.  This is not required,
but if it is done, then Fossil will automatically put itself into a chroot
jail for the user who owns the fossil repository before reading any information
off of the wire.



Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
changes - consult your system's documentation for details.






















Using inetd or xinetd is a more complex setup
than the "standalone" server, but it has the
advantage of only using system resources when an actual connection is
attempted.  If no-one ever connects to that port, a Fossil server will
not (automatically) run. It has the disadvantage of requiring "root" access
and therefore may not normally be available to lower-priced "shared" servers
on the Internet.

The configuration for <tt>stunnel</tt> is similar, but it is covered in
[./ssl.wiki#stunnel|a separate document].
</blockquote>

<h2 id="cgi">Fossil as CGI</h2>

<blockquote>

A Fossil server can also be run from an ordinary web server as a CGI program.
This feature allows Fossil to be seamlessly integrated into a larger website.
CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
implemented.



To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
of your web server and having content like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /home/fossil/repo.fossil
</pre></blockquote>



As always, adjust your paths appropriately.
It may be necessary to set permissions properly, or to modify an ".htaccess"
file or make other server-specific changes.  Consult the documentation
for your particular web server. In particular, the following permissions are
<em>normally</em> required (but, again, may be different for a particular
configuration):

<ul>
  <li>The Fossil binary (/usr/bin/fossil in the example above)
  must be readable/executable, and ALL directories leading up to it
  must be readable by the process which executes the CGI.</li>
  <li>ALL directories leading to the CGI script must also be readable and the CGI
  script itself must be executable for the user under which it will run (which often differs
  from the one running the web server - consult your site's documentation or administrator).</li>
  <li>The repository file AND the directory containing it must be writable by the same account
  which executes the Fossil binary (again, this might differ from the WWW user). The directory
  needs to be writable so that sqlite can write its journal files.</li>
  <li>Fossil must be able to create temporary files, the default directory
  for which depends on the OS.  When the CGI process is operating within
  a chroot, ensure that this directory exists and is readable/writeable
  by the user who executes the Fossil binary.</li>
</ul>



Once the script is set up correctly, and assuming your server is also set
correctly, you should be able to access your repository with a URL like:
<b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
accessible under "cgi-bin", which would be a typical deployment on Apache
for instance).


To serve multiple repositories from a directory using CGI, use the "directory:"
tag in the CGI script rather than "repository:".   You might also want to add
a "notfound:" tag to tell where to redirect if the particular repository requested
by the URL is not found:

<blockquote><pre>
#!/usr/bin/fossil
directory: /home/fossil/repos
notfound: http://url-to-go-to-if-repo-not-found/
</pre></blockquote>



Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).



Additional options available to the CGI script are documented in the
source code.  As of 2017-07-02, the available options are described at
[/artifact/9a52a07b?ln=1777-1824|main.c lines 1777 through 1824].

</blockquote>


<h2 id="scgi">Fossil as SCGI</h2>
<blockquote>


The [/help/server|fossil server] command, described above as a way of
starting a stand-alone web server, can also be used for SCGI.  Simply add
the --scgi command-line option and the stand-alone server will interpret
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP.  This can
be used in combination with a webserver (such as [http://nginx.org|Nginx])
that does not support CGI.  A typical Nginx configuration to support SCGI
with Fossil would look something like this:

<blockquote><pre>
location /demo_project/ {
    include scgi_params;
    scgi_pass localhost:9000;
    scgi_param SCRIPT_NAME "/demo_project";
    scgi_param HTTPS "on";
}
</pre></blockquote>


Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default,
so it is necessary to provide the SCRIPT_NAME parameter in the configuration.
Failure to do this will cause Fossil to return an error.



All of the features of the stand-alone server mode described above,
such as the ability to serve a directory full of Fossil repositories
rather than just a single repository, work the same way in SCGI mode.



For security, it is probably a good idea to add the --localhost option
to the [/help/server|fossil server] command to prevent Fossil from accepting
off-site connections.  One might also want to specify the listening TCP port
number, rather than letting Fossil choose one for itself, just to avoid
ambiguity.  A typical command to start a Fossil SCGI server
would be something like this:

<blockquote><pre>
fossil server $REPOSITORY --scgi --localhost --port 9000
</pre></blockquote>
</blockquote>

<h2 id="tls">Securing a repository with TLS</h2>


<blockquote>












  Fossil's built-in HTTP server (e.g. "fossil server") does not support
  TLS, but there are multiple ways to protect your Fossil server with
  TLS. All of this is covered in a separate document, <a
  href="./ssl.wiki">Using TLS-Encrypted Communications with Fossil</a>.





</blockquote>

<h2 id="loadmgmt">Managing Server Load</h2>

<blockquote>

A Fossil server is very efficient and normally presents a very light
load on the server.
The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
[http://www.linode.com | Linode.com] hosting 65 other repositories in
addition to Fossil (and including some very high-traffic sites such
as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
it has a typical load of 0.05 to 0.1.  A single HTTP request to Fossil
normally takes less than 10 milliseconds of CPU time to complete, so
requests can be arriving at a continuous rate of 20 or more per second,
and the CPU can still be mostly idle.


However, there are some Fossil web pages that can consume large
amounts of CPU time, especially on repositories with a large number
of files or with long revision histories.  High CPU usage pages include
[/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
[/help?cmd=/annotate | /annotate] and others.  On very large repositories,
these commands can take 15 seconds or more of CPU time.
If these kinds of requests arrive too quickly, the load average on the
server can grow dramatically, making the server unresponsive.


Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:

<ol>
  <li><p>An optional cache is available that remembers the 10 most recently
      requested /zip or /tarball pages and returns the precomputed answer
      if the same page is requested again.</p>
  <li><p>Page requests can be configured to fail with a
      [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 | "503 Server Overload"]
      HTTP error if an expensive request is received while the host load
      average is too high.</p>
</ol>

Both of these load-control mechanisms are turned off by default, but they
are recommended for high-traffic sites.


The webpage cache is activated using the [/help?cmd=cache|fossil cache init]
command-line on the server.  Add a -R option to specify the specific repository
for which to enable caching.  If running this command as root, be sure to
"chown" the cache database (which is a separate file in the same directory
and with the same name as the repository but with the suffix changed to ".cache")
to give it write permission for the userid of the webserver.


To activate the server load control feature
visit the AdminAccess setup page in the administrative web
interface; in the "<b>Server Load Average Limit</b>" box
enter the load average threshold above which "503 Server
Overload" replies will be issued for expensive requests.  On the
self-hosting Fossil server, that value is set to 1.5, but you could easily
set it higher on a multi-core server.


The maximum load average can also be set on the command line using
commands like this:
<blockquote><pre>
fossil set max-loadavg 1.5
fossil all set max-loadavg 1.5
</pre></blockquote>

The second form is especially useful for changing the maximum load average
simultaneously on a large number of repositories.


Note that this load-average limiting feature is only available on operating
systems that support the "getloadavg()" API.  Most modern Unix systems have
this interface, but Windows does not, so the feature will not work on Windows.
Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg"
file in the "proc" virtual filesystem.  If you are running a Fossil instance
inside a chroot() jail on Linux, you will need to make the "/proc" file
system available inside that jail in order for this feature to work.  On
the [./selfhost.wiki|self-hosting Fossil repositories], this was accomplished
by adding a line to the "/etc/fstab" file that looks like:

<blockquote><pre>
chroot_jail_proc /home/www/proc proc ro 0 0
</pre></blockquote>

The /home/www/proc pathname should be adjusted so that the "/proc" component is
in the root of the chroot jail, of course.


To see if the load-average limiter is functional, visit the [/test_env] page
of the server to view the current load average.  If the value for the load
average is greater than zero, that means that it is possible to activate
the load-average limiter on that repository.  If the load average shows
exactly "0.0", then that means that Fossil is unable to find the load average
(either because it is in a chroot() jail without /proc access, or because
it is running on a system that does not support "getloadavg()") and so the
load-average limiter will not function.

</blockquote>

<
|
<
<
|




|
<
|
<
|


|

<
|
<
<

<

|
|
|
|

<



<
<
|
<
|


<

|
|

<
>

|






<
|
<
<
<
<
<
<
<
>
>
>
>
|
<
>
>
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
|
<
>

<
<
>
|
<
<
<
>




<





<







|
|





<





<




<
>
>


|
<













<
>


<
>
>




<
>
>


<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|





|
|
|
|
|
|
<
<
<
<




<
>
>


<




>

>








|
|
|
|
|
|
|
|
|
|
|
|
|

>

>





|
>




<





<
>
>


<
>
>



>


>
|
<

>







<








<
>


|
|

<
>
>



<
>
>


|



<





|
<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
>
>
>
>
>


|
<
|
>







|
|

<
>








<
>


<

|
|
|
|
|
|
|

<


<
>






<
>

|
|


|

<
>






<


<
>









<



<


<
>










1

2


3
4
5
6
7
8

9

10
11
12
13
14

15


16

17
18
19
20
21
22

23
24
25


26

27
28
29

30
31
32
33

34
35
36
37
38
39
40
41
42

43







44
45
46
47
48

49
50
51

52






















53
54
55
56

57
58


59
60



61
62
63
64
65

66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89

90
91
92
93

94
95
96
97
98

99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114

115
116
117
118
119
120

121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157




158
159
160
161

162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213

214
215
216
217

218
219
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
235
236

237
238
239
240
241
242
243
244

245
246
247
248
249
250

251
252
253
254
255

256
257
258
259
260
261
262
263

264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284



285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304

305
306
307
308
309
310
311
312
313

314
315
316

317
318
319
320
321
322
323
324
325

326
327

328
329
330
331
332
333
334

335
336
337
338
339
340
341
342

343
344
345
346
347
348
349

350
351

352
353
354
355
356
357
358
359
360
361

362
363
364

365
366

367
368
369
370
371
372
373
374
375
376
377
<title>How To Configure A Fossil Server</title>

<h2>Introduction</h2><blockquote>


<p>A server is not necessary to use Fossil, but a server does help in collaborating with
peers.  A Fossil server also works well as a complete website for a project.
For example, the complete [https://www.fossil-scm.org/] website, including the
page you are now reading,
is just a Fossil server displaying the content of the
self-hosting repository for Fossil.</p>

<p>This article is a guide for setting up your own Fossil server.

<p>See "[./aboutcgi.wiki|How CGI Works In Fossil]" for background
information on the underlying CGI technology.
See "[./sync.wiki|The Fossil Sync Protocol]" for information on the
wire protocol used for client/server communication.</p>
</blockquote>

<h2>Overview</h2><blockquote>


There are basically four ways to set up a Fossil server:

<ol>
<li>A stand-alone server
<li>Using inetd or xinetd or stunnel
<li>CGI
<li>SCGI (a.k.a. SimpleCGI)
</ol>

Each of these can serve either a single repository, or a directory hierarchy
containing many repositories with names ending in ".fossil".
</blockquote>


<a name="standalone"></a>

<h2>Standalone server</h2><blockquote>
The easiest way to set up a Fossil server is to use either the
[/help/server|server] or the [/help/ui|ui] commands:

<ul>
<li><b>fossil server</b> <i>REPOSITORY</i>
<li><b>fossil ui</b> <i>REPOSITORY</i>
</ul>

<p>
The <i>REPOSITORY</i> argument is either the name of the repository file, or
a directory containing many repositories.
Both of these commands start a Fossil server, usually on TCP port 8080, though
a higher numbered port might also be used if 8080 is already occupied.  You can
access these using URLs of the form <b>http://localhost:8080/</b>, or if
<i>REPOSITORY</i> is a directory, URLs of the form
<b>http://localhost:8080/</b><i>repo</i><b>/</b> where <i>repo</i> is the base
name of the repository file without the ".fossil" suffix.

The difference between "ui" and "server" is that "ui" will







also start a web browser and point it
to the URL mentioned above, and the "ui" command binds to
the loopback IP address (127.0.0.1) only so that the "ui" command cannot be
used to serve content to a different machine.
</p>

<p>
If one of the commands above is run from within an open checkout,
then the <i>REPOSITORY</i> argument can be omitted and the checkout is used as

the repository.






















</p>
<p>
Both commands have additional command-line options that can be used to refine
their behavior.  See the [/help/server|online documentation] for an overview.

</p>
</blockquote>


<a name="inetd"></a>
<h2>Fossil as an inetd/xinetd or stunnel service</h2><blockquote>



<p>
A Fossil server can be launched on-demand by inetd or xinetd using
the [/help/http|fossil http] command. To launch Fossil from inetd, modify
your inetd configuration file (typically "/etc/inetd.conf") to contain a
line something like this:

<blockquote>
<pre>
80 stream tcp nowait.1000 root /usr/bin/fossil /usr/bin/fossil http /home/fossil/repo.fossil
</pre>
</blockquote>

In this example, you are telling "inetd" that when an incoming connection
appears on TCP port "80", that it should launch the binary "/usr/bin/fossil"
program with the arguments shown.
Obviously you will
need to modify the pathnames for your particular setup.
The final argument is either the name of the fossil repository to be served,
or a directory containing multiple repositories.
</p>
<p>
If you use a non-standard TCP port on
systems where the port-specification must be a symbolic name and cannot be
numeric, add the desired name and port to /etc/services.  For example, if
you want your Fossil server running on TCP port 12345 instead of 80, you
will need to add:

<blockquote>
<pre>
fossil          12345/tcp  #fossil server
</pre>
</blockquote>

and use the symbolic name ('fossil' in this example) instead of the numeral ('12345')
in inetd.conf. For details, see the relevant section in your system's documentation, e.g.
the [https://www.freebsd.org/doc/en/books/handbook/network-inetd.html|FreeBSD Handbook] in
case you use FreeBSD.

</p>
<p>
If your system is running xinetd, then the configuration is likely to be
in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d".
An xinetd configuration file will appear like this:</p>

<blockquote>
<pre>
service http
{
  port = 80
  socket_type = stream
  wait = no
  user = root
  server = /usr/bin/fossil
  server_args = http /home/fossil/repos/
}
</pre>
</blockquote>

<p>
The xinetd example above has Fossil configured to serve multiple
repositories, contained under the "/home/fossil/repos/" directory.

</p>
<p>
In both cases notice that Fossil was launched as root.  This is not required,
but if it is done, then Fossil will automatically put itself into a chroot
jail for the user who owns the fossil repository before reading any information
off of the wire.

</p>
<p>
Inetd or xinetd must be enabled, and must be (re)started whenever their configuration
changes - consult your system's documentation for details.

</p>
<p>
[https://www.stunnel.org/ | Stunnel version 5] is an inetd-like process that
accepts and decodes SSL-encrypted connections.  Fossil can be run directly from
stunnel in a manner similar to inetd and xinetd.  This can be used to provide
a secure link to a Fossil project.  The configuration needed to get stunnel5
to invoke Fossil is very similar to the inetd and xinetd examples shown above.
The relevant parts of an stunnel configuration might look something
like the following:
<blockquote><pre><nowiki>
[https]
accept       = www.ubercool-project.org:443
TIMEOUTclose = 0
exec         = /usr/bin/fossil
execargs     = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
</nowiki></pre></blockquote>
See the stunnel5 documentation for further details about the /etc/stunnel/stunnel.conf
configuration file.  Note that the [/help/http|fossil http] command should include
the --https option to let Fossil know to use "https" instead of "http" as the scheme
on generated hyperlinks.
<p>
Using inetd or xinetd or stunnel is a more complex setup
than the "standalone" server, but it has the
advantage of only using system resources when an actual connection is
attempted.  If no-one ever connects to that port, a Fossil server will
not (automatically) run. It has the disadvantage of requiring "root" access
and therefore may not normally be available to lower-priced "shared" servers
on the internet.
</p>
</blockquote>
<a name="cgi"></a>
<h2>Fossil as CGI</h2><blockquote>
<p>




A Fossil server can also be run from an ordinary web server as a CGI program.
This feature allows Fossil to be seamlessly integrated into a larger website.
CGI is how the [./selfhost.wiki | self-hosting fossil repositories] are
implemented.

</p>
<p>
To run Fossil as CGI, create a CGI script (here called "repo") in the CGI directory
of your web server and having content like this:

<blockquote><pre>
#!/usr/bin/fossil
repository: /home/fossil/repo.fossil
</pre></blockquote>
</p>

<p>
As always, adjust your paths appropriately.
It may be necessary to set permissions properly, or to modify an ".htaccess"
file or make other server-specific changes.  Consult the documentation
for your particular web server. In particular, the following permissions are
<em>normally</em> required (but, again, may be different for a particular
configuration):

<ul>
<li>The Fossil binary (/usr/bin/fossil in the example above)
must be readable/executable, and ALL directories leading up to it
must be readable by the process which executes the CGI.</li>
<li>ALL directories leading to the CGI script must also be readable and the CGI
script itself must be executable for the user under which it will run (which often differs
from the one running the web server - consult your site's documentation or administrator).</li>
<li>The repository file AND the directory containing it must be writable by the same account
which executes the Fossil binary (again, this might differ from the WWW user). The directory
needs to be writable so that sqlite can write its journal files.</li>
<li>Fossil must be able to create temporary files, the default directory
for which depends on the OS.  When the CGI process is operating within
a chroot, ensure that this directory exists and is readable/writeable
by the user who executes the Fossil binary.</li>
</ul>
</p>

<p>
Once the script is set up correctly, and assuming your server is also set
correctly, you should be able to access your repository with a URL like:
<b>http://mydomain.org/cgi-bin/repo</b> (assuming the "repo" script is
accessible under "cgi-bin", which would be a typical deployment on Apache
for instance).
</p>
<p>
To serve multiple repositories from a directory using CGI, use the "directory:"
tag in the CGI script rather than "repository:".   You might also want to add
a "notfound:" tag to tell where to redirect if the particular repository requested
by the URL is not found:

<blockquote><pre>
#!/usr/bin/fossil
directory: /home/fossil/repos
notfound: http://url-to-go-to-if-repo-not-found/
</pre></blockquote>

</p>
<p>
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).

</p>
<p>
Additional options available to the CGI script are documented in the
source code.  As of 2017-07-02, the available options are described at
[/artifact/9a52a07b?ln=1777-1824|main.c lines 1777 through 1824].
</p>
</blockquote>

<a name="scgi"></a>
<h2>Fossil as SCGI</h2><blockquote>


<p>
The [/help/server|fossil server] command, described above as a way of
starting a stand-alone web server, can also be used for SCGI.  Simply add
the --scgi command-line option and the stand-alone server will interpret
and respond to the SimpleCGI or SCGI protocol rather than raw HTTP.  This can
be used in combination with a webserver (such as [http://nginx.org|Nginx])
that does not support CGI.  A typical Nginx configuration to support SCGI
with Fossil would look something like this:

<blockquote><pre>
location /demo_project/ {
    include scgi_params;
    scgi_pass localhost:9000;
    scgi_param SCRIPT_NAME "/demo_project";
    scgi_param HTTPS "on";
}
</pre></blockquote>

<p>
Note that Fossil requires the SCRIPT_NAME variable
in order to function properly, but Nginx does not provide this
variable by default.
So it is necessary to provide the SCRIPT_NAME parameter in the configuration.
Failure to do this will cause Fossil to return an error.

</p>
<p>
All of the features of the stand-alone server mode described above,
such as the ability to serve a directory full of Fossil repositories
rather than just a single repository, work the same way in SCGI mode.

</p>
<p>
For security, it is probably a good idea to add the --localhost option
to the [/help/server|fossil server] command to prevent Fossil from accepting
off-site connections.  And one might want to specify the listening TCP port
number, rather than letting Fossil choose one for itself, just to avoid
ambiguity.  A typical command to start a Fossil SCGI server
would be something like this:

<blockquote><pre>
fossil server $REPOSITORY --scgi --localhost --port 9000
</pre></blockquote>
</blockquote>

<h2>Securing a repository with SSL</h2><blockquote>

<p>
Using either CGI or SCGI, it is trivial to use SSL to
secure the server.  Simply set up the Fossil CGI scripts etc. as above,
but modify the Apache (or IIS, etc.) server to require SSL (that is, a
URL with "https://") in order to access the CGI script directory.  This
may also be accomplished (on Apache, at least) using appropriate
".htaccess" rules.
</p>
<p>
If you are using "inetd" to serve your repository, then you simply need
to add "/usr/bin/stunnel" (perhaps on a different path, depending on your
setup) before the command line to launch Fossil.
</p>
<p>
At this stage, the standalone server (e.g. "fossil server") does not



support SSL.
</p>
<p>
For more information, see <a href="./ssl.wiki">Using SSL with Fossil</a>.
</p>
</blockquote>

<a name="loadmgmt"></a>

<h2>Managing Server Load</h2><blockquote>
<p>
A Fossil server is very efficient and normally presents a very light
load on the server.
The Fossil [./selfhost.wiki | self-hosting server] is a 1/24th slice VM at
[http://www.linode.com | Linode.com] hosting 65 other repositories in
addition to Fossil (and including some very high-traffic sites such
as [http://www.sqlite.org] and [http://system.data.sqlite.org]) and
it has a typical load of 0.05 to 0.1.  A single HTTP request to Fossil
normally takes less than 10 milliseconds of CPU time to complete.  So
requests can be arriving at a continuous rate of 20 or more per second
and the CPU can still be mostly idle.

<p>
However, there are some Fossil web pages that can consume large
amounts of CPU time, especially on repositories with a large number
of files or with long revision histories.  High CPU usage pages include
[/help?cmd=/zip | /zip], [/help?cmd=/tarball | /tarball],
[/help?cmd=/annotate | /annotate] and others.  On very large repositories,
these commands can take 15 seconds or more of CPU time.
If these kinds of requests arrive too quickly, the load average on the
server can grow dramatically, making the server unresponsive.

<p>
Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:

<ol>
<li><p>An optional cache is available that remembers the 10 most recently
    requested /zip or /tarball pages and returns the precomputed answer
    if the same page is requested again.
<li><p>Page requests can be configured to fail with a
    [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 | "503 Server Overload"]
    HTTP error if an expensive request is received while the host load
    average is too high.
</ol>

Both of these load-control mechanisms are turned off by default, but they
are recommended for high-traffic sites.

<p>
The webpage cache is activated using the [/help?cmd=cache|fossil cache init]
command-line on the server.  Add a -R option to specify the specific repository
for which to enable caching.  If running this command as root, be sure to
"chown" the cache database (which is a separate file in the same directory
and with the same name as the repository but with the suffix changed to ".cache")
to give it write permission for the userid of the webserver.

<p>
To activate the server load control feature
visit the /Admin/Access setup page in the administrative web
interface and in the "<b>Server Load Average Limit</b>" box
enter the load average threshold above which "503 Server
Overload" replies will be issued for expensive requests.  On the
self-host Fossil server, that value is set to 1.5.  But you could easily
set it higher on a multi-core server.

<p>
The maximum load average can also be set on the command line using
commands like this:
<blockquote><pre>
fossil set max-loadavg 1.5
fossil all set max-loadavg 1.5
</pre></blockquote>

The second form is especially useful for changing the maximum load average
simultaneously on a large number of repositories.

<p>
Note that this load-average limiting feature is only available on operating
systems that support the "getloadavg()" API.  Most modern Unix systems have
this interface, but Windows does not, so the feature will not work on Windows.
Note also that Linux implements "getloadavg()" by accessing the "/proc/loadavg"
file in the "proc" virtual filesystem.  If you are running a Fossil instance
inside a chroot() jail on Linux, you will need to make the "/proc" file
system available inside that jail in order for this feature to work.  On
the [./selfhost.wiki|self-hosting Fossil repositories], this was accomplished
by adding a line to the "/etc/fstab" file that looks like:

<blockquote><pre>
chroot_jail_proc /home/www/proc proc ro 0 0
</pre></blockquote>

The /home/www/proc pathname should be adjusted so that the "/proc" component is
in the root of the chroot jail, of course.

<p>
To see if the load-average limiter is functional, visit the [/test_env] page
of the server to view the current load average.  If the value for the load
average is greater than zero, that means that it is possible to activate
the load-average limiter on that repository.  If the load average shows
exactly "0.0", then that means that Fossil is unable to find the load average
(either because it is in a chroot() jail without /proc access, or because
it is running on a system that does not support "getloadavg()") and so the
load-average limiter will not function.

</blockquote>

Changes to www/ssl.wiki.

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
way to serve via HTTP over TLS, a.k.a. HTTPS, even when you've linked
Fossil to OpenSSL. To serve a Fossil repository via HTTPS, you must put
it behind some kind of HTTPS proxy.


<h3 id="stunnel">stunnel Alone</h3>

[https://www.stunnel.org/ | <tt>stunnel</tt>] is an
[https://en.wikipedia.org/wiki/Inetd | <tt>inetd</tt>]-like process that
accepts and decodes TLS-encrypted connections. It can directly proxy
Fossil communications, allowing secure TLS-encrypted communications to a
Fossil repository server. You simply need to install <tt>stunnel</tt>
and then place something like this in its main configuration file,
<tt>stunnel.conf</tt>:




<nowiki><pre>
    [https]
    accept       = www.ubercool-project.org:443
    TIMEOUTclose = 0
    exec         = /usr/bin/fossil
    execargs     = /usr/bin/fossil http /home/fossil/ubercool.fossil --https
</pre></nowiki>

The directory where that file goes varies between OSes, so check the man
pages on your system to find out where it should be locally.

See the <tt>stunnel</tt> documentation for further details about this
configuration file.

It is important that the [/help/http | <tt>fossil http</tt>] command in
that configuration include the <tt>--https</tt> option to let Fossil
know to use "<tt>https</tt>" instead of "<tt>http</tt>" as the URL
scheme on generated hyperlinks.


<h3 id="althttpd">stunnel + althttpd</h3>

The public SQLite and Fossil web sites can't just use stunnel + Fossil
because parts of the web site are static, served by
[https://www.sqlite.org/docsrc/file/misc/althttpd.c|a separate web







|
|
|
|
<
<
<

>
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







209
210
211
212
213
214
215
216
217
218
219



220
221
222
223
224

















225
226
227
228
229
230
231
way to serve via HTTP over TLS, a.k.a. HTTPS, even when you've linked
Fossil to OpenSSL. To serve a Fossil repository via HTTPS, you must put
it behind some kind of HTTPS proxy.


<h3 id="stunnel">stunnel Alone</h3>

Conceptually, the simplest option is to [https://www.stunnel.org/|set up
stunnel].  A typical configuration is to run Fossil as an HTTP server
bound to localhost only, then export access to it via HTTPS with stunnel
encrypting access to Fossil instance hiding behind it.




The difficulty comes in configuring it, which really wants a guide that
no one has written for us yet. Until that appears, you'll have to read
the stunnel documentation and that of your TLS certificate provider to
work out how to set this up.



















<h3 id="althttpd">stunnel + althttpd</h3>

The public SQLite and Fossil web sites can't just use stunnel + Fossil
because parts of the web site are static, served by
[https://www.sqlite.org/docsrc/file/misc/althttpd.c|a separate web

Changes to www/tls-nginx.md.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    proxy access to another HTTP server, this option is overkill for our
    purposes.  nginx is itself a fully featured HTTP server, so we will
    choose in this guide not to make nginx reinterpret Fossil’s
    implementation of HTTP.

*   **CGI** — This method is simple but inefficient, because it launches
    a separate Fossil instance on every HTTP hit.

    Since Fossil is a relatively small self-contained program, and it’s
    designed to start up quickly, this method can work well in a
    surprisingly large number of cases.

    Nevertheless, we will avoid this option in this document because
    we’re already buying into a certain amount of complexity here in
    order to gain power.  There’s no sense in throwing away any of that
................................................................................
`*.example.com` and `*.example.net`; and `local/foo` contains the
configuration for `*.foo.net`.

Here’s an example configuration:

      server {
          server_name .foo.net;

          include local/tls-common;

          charset utf-8;

          access_log /var/log/nginx/foo.net-https-access.log;
           error_log /var/log/nginx/foo.net-https-error.log;

          # Bypass Fossil for the static Doxygen docs
          location /doc/html {
              root /var/www/foo.net;

              location ~* \.(html|ico|css|js|gif|jpg|png)$ {
                  expires 7d;
                  add_header Vary Accept-Encoding;
                  access_log off;
              }
          }

          # Redirect everything else to the Fossil instance
          location / {
              include scgi_params;
              scgi_pass 127.0.0.1:12345;
              scgi_param HTTPS "on";
              scgi_param SCRIPT_NAME "";
          }
................................................................................

The first line tells nginx to accept TLS-encrypted HTTP connections on
the standard HTTPS port. It is the same as `listen 443; ssl on;` in
older versions of nginx.

Since all of those domains share a single TLS certificate, we reference
the same `example.com/*.pem` files written out by Certbot with the
`ssl_certificate*` lines.

The `ssl_dhparam` directive isn’t strictly required, but without it, the
server becomes vulnerable to the [Logjam attack][lja] because some of
the cryptography steps are precomputed, making the attacker’s job much
easier. The parameter file this directive references should be
generated automatically by the Let’s Encrypt package upon installation,
making those parameters unique to your server and thus unguessable. If
................................................................................
    where it can speak HTTPS safely again.

So, from the second `service { }` block, we include this file to set up
the minimal HTTP service we reqiure, `local/http-certbot-only`:

      listen 80;
      listen [::]:80;

      # This is expressed as a rewrite rule instead of an "if" because
      # http://wiki.nginx.org/IfIsEvil
      #rewrite ^(/.well-known/acme-challenge/.*) $1 break;

      # Force everything else to HTTPS with a permanent redirect.
      #return 301 https://$host$request_uri;

As written above, this configuration does nothing other than to tell
nginx that it’s allowed to serve content via HTTP on port 80 as well.

We’ll uncomment the `rewrite` and `return` directives below, when we’re







|







 







|

|

|


|



|






|







 







|







 







|



|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
    proxy access to another HTTP server, this option is overkill for our
    purposes.  nginx is itself a fully featured HTTP server, so we will
    choose in this guide not to make nginx reinterpret Fossil’s
    implementation of HTTP.

*   **CGI** — This method is simple but inefficient, because it launches
    a separate Fossil instance on every HTTP hit.
    
    Since Fossil is a relatively small self-contained program, and it’s
    designed to start up quickly, this method can work well in a
    surprisingly large number of cases.

    Nevertheless, we will avoid this option in this document because
    we’re already buying into a certain amount of complexity here in
    order to gain power.  There’s no sense in throwing away any of that
................................................................................
`*.example.com` and `*.example.net`; and `local/foo` contains the
configuration for `*.foo.net`.

Here’s an example configuration:

      server {
          server_name .foo.net;
      
          include local/tls-common;
      
          charset utf-8;
      
          access_log /var/log/nginx/foo.net-https-access.log;
           error_log /var/log/nginx/foo.net-https-error.log;
      
          # Bypass Fossil for the static Doxygen docs
          location /doc/html {
              root /var/www/foo.net;
      
              location ~* \.(html|ico|css|js|gif|jpg|png)$ {
                  expires 7d;
                  add_header Vary Accept-Encoding;
                  access_log off;
              }
          }
      
          # Redirect everything else to the Fossil instance
          location / {
              include scgi_params;
              scgi_pass 127.0.0.1:12345;
              scgi_param HTTPS "on";
              scgi_param SCRIPT_NAME "";
          }
................................................................................

The first line tells nginx to accept TLS-encrypted HTTP connections on
the standard HTTPS port. It is the same as `listen 443; ssl on;` in
older versions of nginx.

Since all of those domains share a single TLS certificate, we reference
the same `example.com/*.pem` files written out by Certbot with the
`ssl_certificate*` lines. 

The `ssl_dhparam` directive isn’t strictly required, but without it, the
server becomes vulnerable to the [Logjam attack][lja] because some of
the cryptography steps are precomputed, making the attacker’s job much
easier. The parameter file this directive references should be
generated automatically by the Let’s Encrypt package upon installation,
making those parameters unique to your server and thus unguessable. If
................................................................................
    where it can speak HTTPS safely again.

So, from the second `service { }` block, we include this file to set up
the minimal HTTP service we reqiure, `local/http-certbot-only`:

      listen 80;
      listen [::]:80;
  
      # This is expressed as a rewrite rule instead of an "if" because
      # http://wiki.nginx.org/IfIsEvil
      #rewrite ^(/.well-known/acme-challenge/.*) $1 break;
  
      # Force everything else to HTTPS with a permanent redirect.
      #return 301 https://$host$request_uri;

As written above, this configuration does nothing other than to tell
nginx that it’s allowed to serve content via HTTP on port 80 as well.

We’ll uncomment the `rewrite` and `return` directives below, when we’re