Fossil

Check-in [08db3204]
Login

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

Overview
Comment:Updating from trunk. I solved three merge conflicts about hyperlinks.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | annotate_links
Files: files | file ages | folders
SHA1:08db320464c7cd19fe8992da6846c6f0d9cd32fb
User & Date: viriketo 2012-08-08 13:46:37
Context
2012-08-20
13:20
Fixing the automatic calculation of sbs line length, for the case of TABs and UTF8 sequences. I also set the tab size to 4 spaces. check-in: 36cdc17c user: viriketo tags: annotate_links
2012-08-08
13:46
Updating from trunk. I solved three merge conflicts about hyperlinks. check-in: 08db3204 user: viriketo tags: annotate_links
13:22
When using /zip or /tarball without a UUID, use "trunk" instead of "tip" as the default. Ticket [300fc543b24250e256] check-in: eb0933ca user: drh tags: trunk
2012-04-22
10:09
Merging from trunk.

I solved some conflicts on the report for merges (cherrypick/...), adding some comments, and adopted the trunk solution to unchanged checkin messages. check-in: 40debe47 user: viriketo tags: annotate_links

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to VERSION.

1
1.22
|
1
1.23

Changes to auto.def.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
64
65
66
67
68
69
70

71
72
73
74
75
76
77
                         => {Look for openssl in the given path, or auto or none}
    with-zlib:path       => {Look for zlib in the given path}
    with-tcl:path        => {Enable Tcl integration, with Tcl in the specified path}
    internal-sqlite=1    => {Don't use the internal sqlite, use the system one}
    static=0             => {Link a static executable}
    lineedit=1           => {Disable line editing}
    fossil-debug=0       => {Build with fossil debugging enabled}
    json=0        => {Build with fossil JSON API enabled}
}

# sqlite wants these types if possible
cc-with {-includes {stdint.h inttypes.h}} {
    cc-check-types uint32_t uint16_t int16_t uint8_t
}

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

if {[opt-bool fossil-debug]} {
    define-append EXTRA_CFLAGS -DFOSSIL_DEBUG
}

if {[opt-bool json]} {
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON

}

if {[opt-bool static]} {
    # XXX: This will not work on all systems.
    define-append EXTRA_LDFLAGS -static
}








|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
                         => {Look for openssl in the given path, or auto or none}
    with-zlib:path       => {Look for zlib in the given path}
    with-tcl:path        => {Enable Tcl integration, with Tcl in the specified path}
    internal-sqlite=1    => {Don't use the internal sqlite, use the system one}
    static=0             => {Link a static executable}
    lineedit=1           => {Disable line editing}
    fossil-debug=0       => {Build with fossil debugging enabled}
    json=0               => {Build with fossil JSON API enabled}
}

# sqlite wants these types if possible
cc-with {-includes {stdint.h inttypes.h}} {
    cc-check-types uint32_t uint16_t int16_t uint8_t
}

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

if {[opt-bool fossil-debug]} {
    define-append EXTRA_CFLAGS -DFOSSIL_DEBUG
}

if {[opt-bool json]} {
    define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
    define FOSSIL_ENABLE_JSON
}

if {[opt-bool static]} {
    # XXX: This will not work on all systems.
    define-append EXTRA_LDFLAGS -static
}

Changes to autosetup/local.tcl.

18
19
20
21
22
23
24

25
26
27
28
29
		}
	}
}

proc parse-tclconfig-sh-file {filename} {
	foreach line [split [readfile $filename] \n] {
		if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} {

			set tclconfig($name) [string trim $value ']
		}
	}
	return [array get tclconfig]
}







>





18
19
20
21
22
23
24
25
26
27
28
29
30
		}
	}
}

proc parse-tclconfig-sh-file {filename} {
	foreach line [split [readfile $filename] \n] {
		if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} {
			set value [regsub -all {\$\{.*\}} $value ""]
			set tclconfig($name) [string trim $value ']
		}
	}
	return [array get tclconfig]
}

Changes to src/Makefile.

1
2

all:
	$(MAKE) -C ..

|
|
>
1
2
3
all clean:
	$(MAKE) -C .. $(MAKECMDGOALS)

Changes to src/add.c.

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

    file_canonical_name(g.argv[i], &fullName, 0);
    zName = blob_str(&fullName);
    isDir = file_wd_isdir(zName);
    if( isDir==1 ){
      vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
    }else if( isDir==0 ){
      fossil_fatal("not found: %s", zName);
    }else if( file_access(zName, R_OK) ){
      fossil_fatal("cannot open %s", zName);
    }else{
      char *zTreeName = &zName[nRoot];
      db_multi_exec(
         "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)",
         zTreeName







|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

    file_canonical_name(g.argv[i], &fullName, 0);
    zName = blob_str(&fullName);
    isDir = file_wd_isdir(zName);
    if( isDir==1 ){
      vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
    }else if( isDir==0 ){
      fossil_warning("not found: %s", zName);
    }else if( file_access(zName, R_OK) ){
      fossil_fatal("cannot open %s", zName);
    }else{
      char *zTreeName = &zName[nRoot];
      db_multi_exec(
         "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)",
         zTreeName

Changes to src/allrepo.c.

61
62
63
64
65
66
67
68




69
70
71
72
73
74
75
..
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
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
**
** Available operations are:
**
**    ignore     Arguments are repositories that should be ignored
**               by subsequent list, pull, push, rebuild, and sync.
**
**    list | ls  Display the location of all repositories




**
**    pull       Run a "pull" operation on all repositories
**
**    push       Run a "push" on all repositories
**
**    rebuild    Rebuild on all repositories
**
................................................................................
void all_cmd(void){
  int n;
  Stmt q;
  const char *zCmd;
  char *zSyscmd;
  char *zFossil;
  char *zQFilename;
  int nMissing;


  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;

  






  if( g.argc<3 ){
    usage("list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  zCmd = g.argv[2];
  if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
    zCmd = "list";

  }else if( strncmp(zCmd, "push", n)==0 ){
    zCmd = "push -autourl -R";
  }else if( strncmp(zCmd, "pull", n)==0 ){
    zCmd = "pull -autourl -R";
  }else if( strncmp(zCmd, "rebuild", n)==0 ){
    zCmd = "rebuild";
  }else if( strncmp(zCmd, "sync", n)==0 ){
    zCmd = "sync -autourl -R";
  }else if( strncmp(zCmd, "test-integrity", n)==0 ){
    zCmd = "test-integrity";





  }else if( strncmp(zCmd, "ignore", n)==0 ){
    int j;

    db_begin_transaction();
    for(j=3; j<g.argc; j++){
      db_multi_exec("DELETE FROM global_config WHERE name GLOB 'repo:%q'",
         g.argv[j]);






    }
    db_end_transaction(0);
    return;
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "ignore list ls push pull rebuild sync");
  }

  zFossil = quoteFilename(fossil_nameofexe());
  nMissing = 0;

  db_prepare(&q,







     "SELECT DISTINCT substr(name, 6) COLLATE nocase"
     "  FROM global_config"
     " WHERE substr(name, 1, 5)=='repo:' ORDER BY 1"

  );


  while( db_step(&q)==SQLITE_ROW ){
    const char *zFilename = db_column_text(&q, 0);

    if( file_access(zFilename, 0) ){
      nMissing++;

      continue;
    }
    if( !file_is_canonical(zFilename) ) nMissing++;




    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);

    fossil_print("%s\n", zSyscmd);
    fflush(stdout);

    rc = fossil_system(zSyscmd);
    free(zSyscmd);
    free(zQFilename);
    if( stopOnError && rc ){
      nMissing = 0;
      break;
    }
  }

  
  /* If any repositories whose names appear in the ~/.fossil file could not
  ** be found, remove those names from the ~/.fossil file.
  */
  if( nMissing ){
    db_begin_transaction();
    db_reset(&q);
    while( db_step(&q)==SQLITE_ROW ){
      const char *zFilename = db_column_text(&q, 0);
      if( file_access(zFilename, 0) ){
        char *zRepo = mprintf("repo:%s", zFilename);
        db_unset(zRepo, 1);
        free(zRepo);
      }else if( !file_is_canonical(zFilename) ){
        Blob cname;
        char *zRepo = mprintf("repo:%s", zFilename);
        db_unset(zRepo, 1);
        free(zRepo);
        file_canonical_name(zFilename, &cname, 0);
        zRepo = mprintf("repo:%s", blob_str(&cname));
        db_set(zRepo, "1", 1);
        free(zRepo);
      }





    }
    db_reset(&q);
    db_end_transaction(0);
  }
  db_finalize(&q);
}







|
>
>
>
>







 







|
>
>


>

>
>
>
>
>
>

|






>










>
>
>
>
>


>


|
|
>
>
>
>
>
>





|

>

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


>
|
<
>


<
>
>
>
>






>
|
|
>
|



<



>




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

|
<

<

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
..
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
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
**
** Available operations are:
**
**    ignore     Arguments are repositories that should be ignored
**               by subsequent list, pull, push, rebuild, and sync.
**
**    list | ls  Display the location of all repositories.
**               The --ckout option causes all local checkouts to be
**               list instead.
**
**    changes    Shows all local checkouts that have uncommitted changes
**
**    pull       Run a "pull" operation on all repositories
**
**    push       Run a "push" on all repositories
**
**    rebuild    Rebuild on all repositories
**
................................................................................
void all_cmd(void){
  int n;
  Stmt q;
  const char *zCmd;
  char *zSyscmd;
  char *zFossil;
  char *zQFilename;
  int useCheckouts = 0;
  int quiet = 0;
  int testRun = 0;
  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;
  Bag outOfDate;
  
  /* The undocumented --test option causes no changes to occur to any
  ** repository, but instead show what would have happened.  Intended for
  ** test and debugging use.
  */
  testRun = find_option("test",0,0)!=0;

  if( g.argc<3 ){
    usage("changes|list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  zCmd = g.argv[2];
  if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
    zCmd = "list";
    useCheckouts = find_option("ckout","c",0)!=0;
  }else if( strncmp(zCmd, "push", n)==0 ){
    zCmd = "push -autourl -R";
  }else if( strncmp(zCmd, "pull", n)==0 ){
    zCmd = "pull -autourl -R";
  }else if( strncmp(zCmd, "rebuild", n)==0 ){
    zCmd = "rebuild";
  }else if( strncmp(zCmd, "sync", n)==0 ){
    zCmd = "sync -autourl -R";
  }else if( strncmp(zCmd, "test-integrity", n)==0 ){
    zCmd = "test-integrity";
  }else if( strncmp(zCmd, "changes", n)==0 ){
    zCmd = "changes --quiet --header --chdir";
    useCheckouts = 1;
    stopOnError = 0;
    quiet = 1;
  }else if( strncmp(zCmd, "ignore", n)==0 ){
    int j;
    verify_all_options();
    db_begin_transaction();
    for(j=3; j<g.argc; j++){
      char *zSql = mprintf("DELETE FROM global_config"
                           " WHERE name GLOB 'repo:%q'", g.argv[j]);
      if( testRun ){
        fossil_print("%s\n", zSql);
      }else{
        db_multi_exec("%s", zSql);
      }
      fossil_free(zSql);
    }
    db_end_transaction(0);
    return;
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "changes ignore list ls push pull rebuild sync");
  }
  verify_all_options();
  zFossil = quoteFilename(fossil_nameofexe());

  if( useCheckouts ){
    db_prepare(&q,
       "SELECT substr(name, 7) COLLATE nocase, max(rowid)"
       "  FROM global_config"
       " WHERE substr(name, 1, 6)=='ckout:'"
       " GROUP BY 1 ORDER BY 1"
    );
  }else{
    db_prepare(&q,
       "SELECT substr(name, 6) COLLATE nocase, max(rowid)"
       "  FROM global_config"
       " WHERE substr(name, 1, 5)=='repo:'"
       " GROUP BY 1 ORDER BY 1"
    );
  }
  bag_init(&outOfDate);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFilename = db_column_text(&q, 0);
    int rowid = db_column_int(&q, 1);
    if( file_access(zFilename, 0) || !file_is_canonical(zFilename) ){

      bag_insert(&outOfDate, rowid);
      continue;
    }

    if( useCheckouts && file_isdir(zFilename)!=1 ){
      bag_insert(&outOfDate, rowid);
      continue;
    }
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s", zFossil, zCmd, zQFilename);
    if( !quiet || testRun ){
      fossil_print("%s\n", zSyscmd);
      fflush(stdout);
    }
    rc = testRun ? 0 : fossil_system(zSyscmd);
    free(zSyscmd);
    free(zQFilename);
    if( stopOnError && rc ){

      break;
    }
  }
  db_finalize(&q);
  
  /* If any repositories whose names appear in the ~/.fossil file could not
  ** be found, remove those names from the ~/.fossil file.
  */

  if( bag_count(&outOfDate)>0 ){
    Blob sql;
    char *zSep = "(";
    int rowid;
    blob_zero(&sql);
    blob_appendf(&sql, "DELETE FROM global_config WHERE rowid IN ");
    for(rowid=bag_first(&outOfDate); rowid>0; rowid=bag_next(&outOfDate,rowid)){
      blob_appendf(&sql, "%s%d", zSep, rowid);
      zSep = ",";








    }
    blob_appendf(&sql, ")");
    if( testRun ){
      fossil_print("%s\n", blob_str(&sql));
    }else{
      db_multi_exec(blob_str(&sql));
    }
    blob_reset(&sql);

  }

}

Changes to src/attach.c.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    for(i=0; zFilename[i]; i++){
      if( zFilename[i]=='/' && zFilename[i+1]!=0 ){ 
        zFilename = &zFilename[i+1];
        i = -1;
      }
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      zUrlTail = mprintf("tkt=%s&amp;file=%t", zTarget, zFilename);
    }else{
      zUrlTail = mprintf("page=%t&amp;file=%t", zTarget, zFilename);
    }
    @
    @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
    @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
    if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
    if( zComment && zComment[0] ){
      @ %w(zComment)<br />







|

|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    for(i=0; zFilename[i]; i++){
      if( zFilename[i]=='/' && zFilename[i+1]!=0 ){ 
        zFilename = &zFilename[i+1];
        i = -1;
      }
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
    }else{
      zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
    }
    @
    @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
    @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
    if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
    if( zComment && zComment[0] ){
      @ %w(zComment)<br />

Changes to src/blob.c.

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
...
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
....
1079
1080
1081
1082
1083
1084
1085











  if( whence==BLOB_SEEK_SET ){
    p->iCursor = offset;
  }else if( whence==BLOB_SEEK_CUR ){
    p->iCursor += offset;
  }else if( whence==BLOB_SEEK_END ){
    p->iCursor = p->nUsed + offset - 1;
  }
  if( p->iCursor<0 ){
    p->iCursor = 0;
  }
  if( p->iCursor>p->nUsed ){
    p->iCursor = p->nUsed;
  }
  return p->iCursor;
}

/*
................................................................................

/*
** Initialize a blob to be the content of a file.  If the filename
** is blank or "-" then read from standard input.
**
** Any prior content of the blob is discarded, not freed.
**
** Return the number of bytes read.  Return -1 for an error.

*/
int blob_read_from_file(Blob *pBlob, const char *zFilename){
  int size, got;
  FILE *in;
  if( zFilename==0 || zFilename[0]==0
        || (zFilename[0]=='-' && zFilename[1]==0) ){
    return blob_read_from_channel(pBlob, stdin, -1);
................................................................................
  assert( (pIn->iCursor+nLen)  <= pIn->nUsed );
  if( nLen ){
    memcpy( pDest, pIn->aData, nLen );
    pIn->iCursor += nLen;
  }
  return nLen;
}


















<
<
<







 







|
>







 







>
>
>
>
>
>
>
>
>
>
>
437
438
439
440
441
442
443



444
445
446
447
448
449
450
...
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
  if( whence==BLOB_SEEK_SET ){
    p->iCursor = offset;
  }else if( whence==BLOB_SEEK_CUR ){
    p->iCursor += offset;
  }else if( whence==BLOB_SEEK_END ){
    p->iCursor = p->nUsed + offset - 1;
  }



  if( p->iCursor>p->nUsed ){
    p->iCursor = p->nUsed;
  }
  return p->iCursor;
}

/*
................................................................................

/*
** Initialize a blob to be the content of a file.  If the filename
** is blank or "-" then read from standard input.
**
** Any prior content of the blob is discarded, not freed.
**
** Return the number of bytes read. Calls fossil_panic() error (i.e.
** it exit()s and does not return).
*/
int blob_read_from_file(Blob *pBlob, const char *zFilename){
  int size, got;
  FILE *in;
  if( zFilename==0 || zFilename[0]==0
        || (zFilename[0]=='-' && zFilename[1]==0) ){
    return blob_read_from_channel(pBlob, stdin, -1);
................................................................................
  assert( (pIn->iCursor+nLen)  <= pIn->nUsed );
  if( nLen ){
    memcpy( pDest, pIn->aData, nLen );
    pIn->iCursor += nLen;
  }
  return nLen;
}

/*
** Swaps the contents of the given blobs. Results
** are unspecified if either value is NULL or both
** point to the same blob.
*/
void blob_swap( Blob *pLeft, Blob *pRight ){
  Blob swap = *pLeft;
  *pLeft = *pRight;
  *pRight = swap;
}

Changes to src/branch.c.

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
354
355
356
357
358
359
360
361
362
363
364

365
366
367
368
369
370
371
...
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
    style_submenu_element("Color-Test", "Color-Test", "brlist?colortest");
  }else{
    style_submenu_element("All", "All", "brlist?all");
  }
  login_anonymous_available();
  style_sidebox_begin("Nomenclature:", "33%");
  @ <ol>
  @ <li> An <div class="sideboxDescribed"><a href="brlist">
  @ open branch</a></div> is a branch that has one or
  @ more <a href="leaves">open leaves.</a>
  @ The presence of open leaves presumably means
  @ that the branch is still being extended with new check-ins.</li>
  @ <li> A <div class="sideboxDescribed"><a href="brlist?closed">
  @ closed branch</a></div> is a branch with only
  @ <div class="sideboxDescribed"><a href="leaves?closed">
  @ closed leaves</a></div>.
  @ Closed branches are fixed and do not change (unless they are first
  @ reopened)</li>
  @ </ol>
  style_sidebox_end();

  branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
................................................................................
      @ <ul>
      cnt++;
    }
    if( colorTest ){
      const char *zColor = hash_color(zBr);
      @ <li><span style="background-color: %s(zColor)">
      @ %h(zBr) &rarr; %s(zColor)</span></li>
    }else if( g.perm.History ){
      @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
    }else{
      @ <li><b>%h(zBr)</b></li>

    }
  }
  if( cnt ){
    @ </ul>
  }
  db_finalize(&q);
  @ <script  type="text/JavaScript">
................................................................................
/*
** This routine is called while for each check-in that is rendered by
** the timeline of a "brlist" page.  Add some additional hyperlinks
** to the end of the line.
*/
static void brtimeline_extra(int rid){
  Stmt q;
  if( !g.perm.History ) return;
  db_prepare(&q, 
    "SELECT substr(tagname,5) FROM tagxref, tag"
    " WHERE tagxref.rid=%d"
    "   AND tagxref.tagid=tag.tagid"
    "   AND tagxref.tagtype>0"
    "   AND tag.tagname GLOB 'sym-*'",
    rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTagName = db_column_text(&q, 0);
    @ <a href="%s(g.zTop)/timeline?r=%T(zTagName)">[timeline]</a>
  }
  db_finalize(&q);
}

/*
** WEBPAGE: brtimeline
**







|

|


|

|







 







<
<

<
>







 







|










|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
354
355
356
357
358
359
360


361

362
363
364
365
366
367
368
369
...
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
    style_submenu_element("Color-Test", "Color-Test", "brlist?colortest");
  }else{
    style_submenu_element("All", "All", "brlist?all");
  }
  login_anonymous_available();
  style_sidebox_begin("Nomenclature:", "33%");
  @ <ol>
  @ <li> An <div class="sideboxDescribed">%z(href("brlist"))
  @ open branch</a></div> is a branch that has one or
  @ more %z(href("leaves"))open leaves.</a>
  @ The presence of open leaves presumably means
  @ that the branch is still being extended with new check-ins.</li>
  @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
  @ closed branch</a></div> is a branch with only
  @ <div class="sideboxDescribed">%z(href("leaves?closed"))
  @ closed leaves</a></div>.
  @ Closed branches are fixed and do not change (unless they are first
  @ reopened)</li>
  @ </ol>
  style_sidebox_end();

  branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
................................................................................
      @ <ul>
      cnt++;
    }
    if( colorTest ){
      const char *zColor = hash_color(zBr);
      @ <li><span style="background-color: %s(zColor)">
      @ %h(zBr) &rarr; %s(zColor)</span></li>


    }else{

      @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li>
    }
  }
  if( cnt ){
    @ </ul>
  }
  db_finalize(&q);
  @ <script  type="text/JavaScript">
................................................................................
/*
** This routine is called while for each check-in that is rendered by
** the timeline of a "brlist" page.  Add some additional hyperlinks
** to the end of the line.
*/
static void brtimeline_extra(int rid){
  Stmt q;
  if( !g.perm.Hyperlink ) return;
  db_prepare(&q, 
    "SELECT substr(tagname,5) FROM tagxref, tag"
    " WHERE tagxref.rid=%d"
    "   AND tagxref.tagid=tag.tagid"
    "   AND tagxref.tagtype>0"
    "   AND tag.tagname GLOB 'sym-*'",
    rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTagName = db_column_text(&q, 0);
    @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a>
  }
  db_finalize(&q);
}

/*
** WEBPAGE: brtimeline
**

Changes to src/browse.c.

75
76
77
78
79
80
81
82
83

84
85
86

87
88
89
90
91
92
93
94
95
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
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
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
*/
void hyperlinked_path(const char *zPath, Blob *pOut, const char *zCI){
  int i, j;
  char *zSep = "";

  for(i=0; zPath[i]; i=j){
    for(j=i; zPath[j] && zPath[j]!='/'; j++){}
    if( zPath[j] && g.perm.History ){
      if( zCI ){

        blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>", 
                     zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
      }else{

        blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", 
                     zSep, g.zTop, j, zPath, j-i, &zPath[i]);
      }
    }else{
      blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
    }
    zSep = "/";
    while( zPath[j]=='/' ){ j++; }
  }
................................................................................
  int rid = 0;
  char *zUuid = 0;
  Blob dirname;
  Manifest *pM = 0;
  const char *zSubdirLink;

  login_check_credentials();
  if( !g.perm.History ){ login_needed(); return; }
  while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
  style_header("File List");
  sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
                          pathelementFunc, 0, 0);

  /* If the name= parameter is an empty string, make it a NULL pointer */
  if( zD && strlen(zD)==0 ){ zD = 0; }
................................................................................
    blob_append(&dirname, "in the top-level directory", -1);
    zPrefix = "";
  }
  if( zCI ){
    char zShort[20];
    memcpy(zShort, zUuid, 10);
    zShort[10] = 0;
    @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix);
    if( zD ){
      style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
      style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
    }else{
      style_submenu_element("All", "All", "%s/dir", g.zTop);
    }
  }else{
    int hasTrunk;
    @ <h2>The union of all files from all check-ins
    @ %s(blob_str(&dirname))</h2>
    hasTrunk = db_exists(
                  "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
                  TAG_BRANCH);
    zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix);
    if( zD ){
      style_submenu_element("Top", "Top", "%s/dir", g.zTop);
      style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip",
                            g.zTop, zD);
      if( hasTrunk ){
        style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk",
                               g.zTop,zD);
      }
    }else{
      style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zTop);
      if( hasTrunk ){
        style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zTop);
      }
    }
  }

  /* Compute the temporary table "localfiles" containing the names
  ** of all files and subdirectories in the zD[] directory.  
  **
................................................................................
      @ </ul></td><td class="browser"><ul class="browser">
      i = 0;
    }
    i++;
    zFN = db_column_text(&q, 0);
    if( zFN[0]=='/' ){
      zFN++;
      @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
    }else if( zCI ){
      const char *zUuid = db_column_text(&q, 1);
      @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li>
    }else{
      @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
      @     </a></li>
    }
  }
  db_finalize(&q);
  manifest_destroy(pM);
  @ </ul></td></tr></table>
  style_footer();
}







|

>
|
|

>
|
|







 







|







 







|

|

|
|

|








|

|
|
<

|
|


|

|







 







|


|

|








75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
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
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
*/
void hyperlinked_path(const char *zPath, Blob *pOut, const char *zCI){
  int i, j;
  char *zSep = "";

  for(i=0; zPath[i]; i=j){
    for(j=i; zPath[j] && zPath[j]!='/'; j++){}
    if( zPath[j] && g.perm.Hyperlink ){
      if( zCI ){
        char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath);
        blob_appendf(pOut, "%s%z%#h</a>", 
                     zSep, zLink, j-i, &zPath[i]);
      }else{
        char *zLink = href("%R/dir?name=%#T", j, zPath);
        blob_appendf(pOut, "%s%z%#h</a>", 
                     zSep, zLink, j-i, &zPath[i]);
      }
    }else{
      blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
    }
    zSep = "/";
    while( zPath[j]=='/' ){ j++; }
  }
................................................................................
  int rid = 0;
  char *zUuid = 0;
  Blob dirname;
  Manifest *pM = 0;
  const char *zSubdirLink;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
  style_header("File List");
  sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
                          pathelementFunc, 0, 0);

  /* If the name= parameter is an empty string, make it a NULL pointer */
  if( zD && strlen(zD)==0 ){ zD = 0; }
................................................................................
    blob_append(&dirname, "in the top-level directory", -1);
    zPrefix = "";
  }
  if( zCI ){
    char zShort[20];
    memcpy(zShort, zUuid, 10);
    zShort[10] = 0;
    @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
    if( zD ){
      style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
      style_submenu_element("All", "All", "%R/dir?name=%t", zD);
    }else{
      style_submenu_element("All", "All", "%R/dir");
    }
  }else{
    int hasTrunk;
    @ <h2>The union of all files from all check-ins
    @ %s(blob_str(&dirname))</h2>
    hasTrunk = db_exists(
                  "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
                  TAG_BRANCH);
    zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
    if( zD ){
      style_submenu_element("Top", "Top", "%R/dir");
      style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD);

      if( hasTrunk ){
        style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk",
                               zD);
      }
    }else{
      style_submenu_element("Tip", "Tip", "%R/dir?ci=tip");
      if( hasTrunk ){
        style_submenu_element("Trunk", "Trunk", "%R/dir?ci=trunk");
      }
    }
  }

  /* Compute the temporary table "localfiles" containing the names
  ** of all files and subdirectories in the zD[] directory.  
  **
................................................................................
      @ </ul></td><td class="browser"><ul class="browser">
      i = 0;
    }
    i++;
    zFN = db_column_text(&q, 0);
    if( zFN[0]=='/' ){
      zFN++;
      @ <li>%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
    }else if( zCI ){
      const char *zUuid = db_column_text(&q, 1);
      @ <li>%z(href("%R/artifact/%s",zUuid))%h(zFN)</a></li>
    }else{
      @ <li>%z(href("%R/finfo?name=%T%T",zPrefix,zFN))%h(zFN)
      @     </a></li>
    }
  }
  db_finalize(&q);
  manifest_destroy(pM);
  @ </ul></td></tr></table>
  style_footer();
}

Changes to src/checkin.c.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
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
...
672
673
674
675
676
677
678
679
680
681
682

683
684
685
686
687
688
689
690
...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
....
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
....
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
....
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  Stmt q;
  int nPrefix = strlen(zPrefix);
  int nErr = 0;
  Blob rewrittenPathname;
  db_prepare(&q, 
    "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
    "  FROM vfile "
    " WHERE file_is_selected(id)"
    "   AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1"
  );
  blob_zero(&rewrittenPathname);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    const char *zDisplayName = zPathname;
    int isDeleted = db_column_int(&q, 1);
................................................................................
**
** Options:
**    --abs-paths       Display absolute pathnames.
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.


** 
** See also: extra, ls, status
*/
void changes_cmd(void){
  Blob report;
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;


  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  blob_zero(&report);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 0, useSha1sum);
  status_report(&report, "", 0, cwdRelative);







  blob_write_to_file(&report, "-");
}

/*
** COMMAND: status
**
** Usage: %fossil status ?OPTIONS?
................................................................................
  }
  blob_appendf(pOut, "C %F\n", blob_str(pComment));
  zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now");
  blob_appendf(pOut, "D %s\n", zDate);
  zDate[10] = ' ';
  db_prepare(&q,
    "SELECT pathname, uuid, origname, blob.rid, isexe, islink,"
    "       file_is_selected(vfile.id)"
    "  FROM vfile JOIN blob ON vfile.mrid=blob.rid"
    " WHERE (NOT deleted OR NOT file_is_selected(vfile.id))"
    "   AND vfile.vid=%d"

    " ORDER BY 1", vid);
  blob_zero(&filename);
  blob_appendf(&filename, "%s", g.zLocalRoot);
  nBasename = blob_size(&filename);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zOrig = db_column_text(&q, 2);
................................................................................
  zComment = find_option("comment","m",1);
  forceFlag = find_option("force", "f", 0)!=0;
  zBranch = find_option("branch","b",1);
  zColor = find_option("bgcolor",0,1);
  zBrClr = find_option("branchcolor",0,1);
  while( (zTag = find_option("tag",0,1))!=0 ){
    if( zTag[0]==0 ) continue;
    azTag = fossil_realloc(azTag, sizeof(char*)*(nTag+2));
    azTag[nTag++] = zTag;
    azTag[nTag] = 0;
  }
  zComFile = find_option("message-file", "M", 1);
  if( find_option("private",0,0) ){
    g.markPrivate = 1;
    if( zBranch==0 ) zBranch = "private";
................................................................................
  */
  if( g.aCommitFile ){
    Blob unmodified;
    memset(&unmodified, 0, sizeof(Blob));
    blob_init(&unmodified, 0, 0);
    db_blob(&unmodified, 
      "SELECT pathname FROM vfile"
      " WHERE chnged = 0 AND origname IS NULL AND file_is_selected(id)"
    );
    if( strlen(blob_str(&unmodified)) ){
      fossil_fatal("file %s has not changed", blob_str(&unmodified));
    }
  }

  /*
................................................................................

  /* Step 1: Insert records for all modified files into the blob 
  ** table. If there were arguments passed to this command, only
  ** the identified fils are inserted (if they have been modified).
  */
  db_prepare(&q,
    "SELECT id, %Q || pathname, mrid, %s FROM vfile "
    "WHERE chnged==1 AND NOT deleted AND file_is_selected(id)",
    g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
  );
  while( db_step(&q)==SQLITE_ROW ){
    int id, rid;
    const char *zFullname;
    Blob content;
    int crnlOk;
................................................................................
    free(zManifestFile);
    blob_reset(&muuid);
  }

  
  /* Update the vfile and vmerge tables */
  db_multi_exec(
    "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND file_is_selected(id);"
    "DELETE FROM vmerge;"
    "UPDATE vfile SET vid=%d;"
    "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL"
    " WHERE file_is_selected(id);"
    , vid, nvid
  );
  db_lset_int("checkout", nvid);

  if( useCksum ){
    /* Verify that the repository checksum matches the expected checksum
    ** calculated before the checkin started (and stored as the R record







|







 







>
>







>
>







>
>
>
>
>
>
>







 







|

|

>
|







 







|







 







|







 







|







 







|



|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
...
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
...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
...
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
....
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
....
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
....
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
  Stmt q;
  int nPrefix = strlen(zPrefix);
  int nErr = 0;
  Blob rewrittenPathname;
  db_prepare(&q, 
    "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)"
    "  FROM vfile "
    " WHERE is_selected(id)"
    "   AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1"
  );
  blob_zero(&rewrittenPathname);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zPathname = db_column_text(&q,0);
    const char *zDisplayName = zPathname;
    int isDeleted = db_column_int(&q, 1);
................................................................................
**
** Options:
**    --abs-paths       Display absolute pathnames.
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**    --header          Identify the repository if there are changes
**    -v                Say "no changes" if there are none
** 
** See also: extra, ls, status
*/
void changes_cmd(void){
  Blob report;
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verbose = find_option("verbose","v",0)!=0;
  int cwdRelative = 0;
  db_must_be_within_tree();
  cwdRelative = determine_cwd_relative_option();
  blob_zero(&report);
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 0, useSha1sum);
  status_report(&report, "", 0, cwdRelative);
  if( verbose && blob_size(&report)==0 ){
    blob_append(&report, "  (none)\n", -1);
  }
  if( showHdr && blob_size(&report)>0 ){
    fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
                 g.zLocalRoot);
  }
  blob_write_to_file(&report, "-");
}

/*
** COMMAND: status
**
** Usage: %fossil status ?OPTIONS?
................................................................................
  }
  blob_appendf(pOut, "C %F\n", blob_str(pComment));
  zDate = date_in_standard_format(zDateOvrd ? zDateOvrd : "now");
  blob_appendf(pOut, "D %s\n", zDate);
  zDate[10] = ' ';
  db_prepare(&q,
    "SELECT pathname, uuid, origname, blob.rid, isexe, islink,"
    "       is_selected(vfile.id)"
    "  FROM vfile JOIN blob ON vfile.mrid=blob.rid"
    " WHERE (NOT deleted OR NOT is_selected(vfile.id))"
    "   AND vfile.vid=%d"
    " ORDER BY if_selected(vfile.id, pathname, origname)",
    vid);
  blob_zero(&filename);
  blob_appendf(&filename, "%s", g.zLocalRoot);
  nBasename = blob_size(&filename);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zOrig = db_column_text(&q, 2);
................................................................................
  zComment = find_option("comment","m",1);
  forceFlag = find_option("force", "f", 0)!=0;
  zBranch = find_option("branch","b",1);
  zColor = find_option("bgcolor",0,1);
  zBrClr = find_option("branchcolor",0,1);
  while( (zTag = find_option("tag",0,1))!=0 ){
    if( zTag[0]==0 ) continue;
    azTag = fossil_realloc((void *)azTag, sizeof(char*)*(nTag+2));
    azTag[nTag++] = zTag;
    azTag[nTag] = 0;
  }
  zComFile = find_option("message-file", "M", 1);
  if( find_option("private",0,0) ){
    g.markPrivate = 1;
    if( zBranch==0 ) zBranch = "private";
................................................................................
  */
  if( g.aCommitFile ){
    Blob unmodified;
    memset(&unmodified, 0, sizeof(Blob));
    blob_init(&unmodified, 0, 0);
    db_blob(&unmodified, 
      "SELECT pathname FROM vfile"
      " WHERE chnged = 0 AND origname IS NULL AND is_selected(id)"
    );
    if( strlen(blob_str(&unmodified)) ){
      fossil_fatal("file %s has not changed", blob_str(&unmodified));
    }
  }

  /*
................................................................................

  /* Step 1: Insert records for all modified files into the blob 
  ** table. If there were arguments passed to this command, only
  ** the identified fils are inserted (if they have been modified).
  */
  db_prepare(&q,
    "SELECT id, %Q || pathname, mrid, %s FROM vfile "
    "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
    g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
  );
  while( db_step(&q)==SQLITE_ROW ){
    int id, rid;
    const char *zFullname;
    Blob content;
    int crnlOk;
................................................................................
    free(zManifestFile);
    blob_reset(&muuid);
  }

  
  /* Update the vfile and vmerge tables */
  db_multi_exec(
    "DELETE FROM vfile WHERE (vid!=%d OR deleted) AND is_selected(id);"
    "DELETE FROM vmerge;"
    "UPDATE vfile SET vid=%d;"
    "UPDATE vfile SET rid=mrid, chnged=0, deleted=0, origname=NULL"
    " WHERE is_selected(id);"
    , vid, nvid
  );
  db_lset_int("checkout", nvid);

  if( useCksum ){
    /* Verify that the repository checksum matches the expected checksum
    ** calculated before the checkin started (and stored as the R record

Changes to src/checkout.c.

289
290
291
292
293
294
295



296
297
298
299
*/
void close_cmd(void){
  int forceFlag = find_option("force","f",0)!=0;
  db_must_be_within_tree();
  if( !forceFlag && unsaved_changes()==1 ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }



  unlink_local_database(1);
  db_close(1);
  unlink_local_database(0);
}







>
>
>




289
290
291
292
293
294
295
296
297
298
299
300
301
302
*/
void close_cmd(void){
  int forceFlag = find_option("force","f",0)!=0;
  db_must_be_within_tree();
  if( !forceFlag && unsaved_changes()==1 ){
    fossil_fatal("there are unsaved changes in the current checkout");
  }
  if( db_is_writeable("repository") ){
    db_multi_exec("DELETE FROM config WHERE name='ckout:%q'", g.zLocalRoot);
  }
  unlink_local_database(1);
  db_close(1);
  unlink_local_database(0);
}

Changes to src/configure.c.

81
82
83
84
85
86
87



88
89
90
91
92
93
94
  { "logo-mimetype",          CONFIGSET_SKIN },
  { "logo-image",             CONFIGSET_SKIN },
  { "background-mimetype",    CONFIGSET_SKIN },
  { "background-image",       CONFIGSET_SKIN },
  { "index-page",             CONFIGSET_SKIN },
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },



#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
#endif

  { "project-name",           CONFIGSET_PROJ },
  { "project-description",    CONFIGSET_PROJ },
  { "manifest",               CONFIGSET_PROJ },







>
>
>







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  { "logo-mimetype",          CONFIGSET_SKIN },
  { "logo-image",             CONFIGSET_SKIN },
  { "background-mimetype",    CONFIGSET_SKIN },
  { "background-image",       CONFIGSET_SKIN },
  { "index-page",             CONFIGSET_SKIN },
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "adunit",                 CONFIGSET_SKIN },
  { "adunit-omit-if-admin",   CONFIGSET_SKIN },
  { "adunit-omit-if-user",    CONFIGSET_SKIN },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT|CONFIGSET_XFER },
#endif

  { "project-name",           CONFIGSET_PROJ },
  { "project-description",    CONFIGSET_PROJ },
  { "manifest",               CONFIGSET_PROJ },

Changes to src/cson_amalgamation.c.

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
....
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
....
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484

#if defined(__cplusplus)
extern "C" {
#endif


    
/**
   Type IDs corresponding to JavaScript/JSON types.
*/
enum cson_type_id {
  /**
    The special "undefined" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */
 CSON_TYPE_NULL = 1,
 /**
    The bool value type.
 */
 CSON_TYPE_BOOL = 2,
 /**
    The integer value type, represented in this library
    by cson_int_t.
 */
 CSON_TYPE_INTEGER = 3,
 /**
    The double value type, represented in this library
    by cson_double_t.
 */
 CSON_TYPE_DOUBLE = 4,
 /** The immutable string type. This library stores strings
    as immutable UTF8.
 */
 CSON_TYPE_STRING = 5,
 /** The "Array" type. */
 CSON_TYPE_ARRAY = 6,
 /** The "Object" type. */
 CSON_TYPE_OBJECT = 7
};
typedef enum cson_type_id cson_type_id;

/**
   This type holds the "vtbl" for type-specific operations when
   working with cson_value objects.

   All cson_values of a given logical type share a pointer to a single
   library-internal instance of this class.
................................................................................
/** Returns true if v is not NULL and has the given type ID. */
static char cson_value_is_a( cson_value const * v, cson_type_id is )
{
    return (v && v->api && (v->api->typeID == is)) ? 1 : 0;
}
#endif

#if 0
cson_type_id cson_value_type_id( cson_value const * v )
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}
#endif

char cson_value_is_undef( cson_value const * v )
{
    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
................................................................................

- (inp) = is a pointer to the pointer to the start of the input.

- (separator) = the separator character

- (end) = a pointer to NULL. i.e. (*end == NULL)

This function scans *inp for the given separator char or a NULL char.
Successive separators at the start of *inp are skipped. The effect is
that, when this function is called in a loop, all neighboring
separators are ignored. e.g. the string "aa.bb...cc" will tokenize to
the list (aa,bb,cc) if the separator is '.' and to (aa.,...cc) if the
separator is 'b'.

Returns 0 (false) if it finds no token, else non-0 (true).







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







 







<




<







 







|







1420
1421
1422
1423
1424
1425
1426






































1427
1428
1429
1430
1431
1432
1433
....
2274
2275
2276
2277
2278
2279
2280

2281
2282
2283
2284

2285
2286
2287
2288
2289
2290
2291
....
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444

#if defined(__cplusplus)
extern "C" {
#endif


    







































/**
   This type holds the "vtbl" for type-specific operations when
   working with cson_value objects.

   All cson_values of a given logical type share a pointer to a single
   library-internal instance of this class.
................................................................................
/** Returns true if v is not NULL and has the given type ID. */
static char cson_value_is_a( cson_value const * v, cson_type_id is )
{
    return (v && v->api && (v->api->typeID == is)) ? 1 : 0;
}
#endif


cson_type_id cson_value_type_id( cson_value const * v )
{
    return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
}


char cson_value_is_undef( cson_value const * v )
{
    return ( !v || !v->api || (v->api==&cson_value_api_undef))
        ? 1 : 0;
}
#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) {       \
................................................................................

- (inp) = is a pointer to the pointer to the start of the input.

- (separator) = the separator character

- (end) = a pointer to NULL. i.e. (*end == NULL)

This function scans *inp for the given separator char or a NUL char.
Successive separators at the start of *inp are skipped. The effect is
that, when this function is called in a loop, all neighboring
separators are ignored. e.g. the string "aa.bb...cc" will tokenize to
the list (aa,bb,cc) if the separator is '.' and to (aa.,...cc) if the
separator is 'b'.

Returns 0 (false) if it finds no token, else non-0 (true).

Changes to src/cson_amalgamation.h.

130
131
132
133
134
135
136

















































137
138
139
140
141
142
143
...
209
210
211
212
213
214
215

216
217
218
219
220
221
222
...
738
739
740
741
742
743
744






745
746
747
748
749
750
751
*/

/** @def CSON_DOUBLE_T_PFMT

printf()-compatible format token for cson_double_t.
*/


















































typedef struct cson_value cson_value;

/** @struct cson_value
   
   The core value type of this API. It is opaque to clients, and
   only the cson public API should be used for setting or
   inspecting their values.
................................................................................
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_true()
   @see cson_value_false()
   @see cson_value_null()
   @see cson_value_free()

*/

/** @var cson_rc

   This object defines the error codes used by cson.

   Library routines which return int values almost always return a
................................................................................
/**
   Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
   any existing contents. Returns cson_rc.IOError if the file cannot be opened.

   @see cson_output_FILE()
*/
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );







/** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
char cson_value_is_undef( cson_value const * v );
/** Returns true if v contains a null value. */
char cson_value_is_null( cson_value const * v );
/** Returns true if v contains a bool value. */
char cson_value_is_bool( cson_value const * v );







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







 







>







 







>
>
>
>
>
>







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
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
*/

/** @def CSON_DOUBLE_T_PFMT

printf()-compatible format token for cson_double_t.
*/

/**
    Type IDs corresponding to JavaScript/JSON types.

    These are only in the public API to allow O(1) client-side
    dispatching based on cson_value types.
*/
enum cson_type_id {
  /**
    The special "undefined" value constant.

    Its value must be 0 for internal reasons.
 */
 CSON_TYPE_UNDEF = 0,
 /**
    The special "null" value constant.
 */
 CSON_TYPE_NULL = 1,
 /**
    The bool value type.
 */
 CSON_TYPE_BOOL = 2,
 /**
    The integer value type, represented in this library
    by cson_int_t.
 */
 CSON_TYPE_INTEGER = 3,
 /**
    The double value type, represented in this library
    by cson_double_t.
 */
 CSON_TYPE_DOUBLE = 4,
 /** The immutable string type. This library stores strings
    as immutable UTF8.
 */
 CSON_TYPE_STRING = 5,
 /** The "Array" type. */
 CSON_TYPE_ARRAY = 6,
 /** The "Object" type. */
 CSON_TYPE_OBJECT = 7
};
/**
   Convenience typedef.
*/
typedef enum cson_type_id cson_type_id;


/**
   Convenience typedef.
*/
typedef struct cson_value cson_value;

/** @struct cson_value
   
   The core value type of this API. It is opaque to clients, and
   only the cson public API should be used for setting or
   inspecting their values.
................................................................................
   @see cson_value_new_integer()
   @see cson_value_new_double()
   @see cson_value_new_bool()
   @see cson_value_true()
   @see cson_value_false()
   @see cson_value_null()
   @see cson_value_free()
   @see cson_value_type_id()
*/

/** @var cson_rc

   This object defines the error codes used by cson.

   Library routines which return int values almost always return a
................................................................................
/**
   Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
   any existing contents. Returns cson_rc.IOError if the file cannot be opened.

   @see cson_output_FILE()
*/
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );

/**
   Returns the virtual type of v, or CSON_TYPE_UNDEF if !v.
*/
cson_type_id cson_value_type_id( cson_value const * v );


/** Returns true if v is null, v->api is NULL, or v holds the special undefined value. */
char cson_value_is_undef( cson_value const * v );
/** Returns true if v contains a null value. */
char cson_value_is_null( cson_value const * v );
/** Returns true if v contains a bool value. */
char cson_value_is_bool( cson_value const * v );

Changes to src/db.c.

113
114
115
116
117
118
119



120
121
122
123
124
125
126
...
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
...
485
486
487
488
489
490
491














492
493
494
495
496
497
498
...
995
996
997
998
999
1000
1001







1002
1003
1004
1005
1006
1007
1008
....
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
....
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
....
1427
1428
1429
1430
1431
1432
1433
1434



1435
1436
1437
1438
1439
1440
1441
....
1711
1712
1713
1714
1715
1716
1717






1718
1719

1720

1721
1722
1723
1724
1725
1726
1727
....
1752
1753
1754
1755
1756
1757
1758





1759
1760
1761
1762
1763
1764
1765
1766
1767
....
1841
1842
1843
1844
1845
1846
1847

1848
1849
1850
1851
1852
1853
1854
....
1906
1907
1908
1909
1910
1911
1912





1913
1914
1915
1916
1917
1918
1919
  int nPrepare;             /* Number of calls to sqlite3_prepare() */
  int nDeleteOnFail;        /* Number of entries in azDeleteOnFail[] */
  struct sCommitHook {
    int (*xHook)(void);         /* Functions to call at db_end_transaction() */
    int sequence;               /* Call functions in sequence order */
  } aHook[5];
  char *azDeleteOnFail[3];  /* Files to delete on a failure */



} db = {0, 0, 0, 0, 0, 0, };

/*
** Arrange for the given file to be deleted on a failure.
*/
void db_delete_on_failure(const char *zFilename){
  assert( db.nDeleteOnFail<count(db.azDeleteOnFail) );
................................................................................
/*
** Begin and end a nested transaction
*/
void db_begin_transaction(void){
  if( db.nBegin==0 ){
    db_multi_exec("BEGIN");
    sqlite3_commit_hook(g.db, db_verify_at_commit, 0);

  }
  db.nBegin++;
}
void db_end_transaction(int rollbackFlag){
  if( g.db==0 ) return;
  if( db.nBegin<=0 ) return;
  if( rollbackFlag ) db.doRollback = 1;
  db.nBegin--;
  if( db.nBegin==0 ){
    int i;






    if( db.doRollback==0 ) leaf_do_pending_checks();

    for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
      db.doRollback |= db.aHook[i].xHook();
    }
    while( db.pAllStmt ){
      db_finalize(db.pAllStmt);
    }
    db_multi_exec(db.doRollback ? "ROLLBACK" : "COMMIT");
................................................................................
  rc = sqlite3_exec(g.db, blob_buffer(&sql), 0, 0, &zErr);
  if( rc!=SQLITE_OK ){
    db_err("%s\n%s", zErr, blob_buffer(&sql));
  }
  blob_reset(&sql);
  return rc;
}















/*
** Execute a query and return a single integer value.
*/
i64 db_int64(i64 iDflt, const char *zSql, ...){
  va_list ap;
  Stmt s;
................................................................................
** Return TRUE if the schema is out-of-date
*/
int db_schema_is_outofdate(void){
  return db_exists("SELECT 1 FROM config"
                   " WHERE name='aux-schema'"
                   "   AND value<>'%s'", AUX_SCHEMA);
}








/*
** Verify that the repository schema is correct.  If it is not correct,
** issue a fatal error and die.
*/
void db_verify_schema(void){
  if( db_schema_is_outofdate() ){
................................................................................


/*
** Open the local database.  If unable, exit with an error.
*/
void db_must_be_within_tree(void){
  if( db_open_local()==0 ){
    fossil_fatal("not within an open checkout");
  }
  db_open_repository(0);
  db_verify_schema();
}

/*
** Close the database connection.
................................................................................
  }else if( argc==2 ){
    zP = (const char*)sqlite3_value_text(argv[1]);
    if( zP ) sqlite3_result_text(context, zP, -1, SQLITE_TRANSIENT);
  }
}

/*
** This is used by the [commit] command.
**
** Return true if either:

**






**     a) Global.aCommitFile is NULL, or
**     b) Global.aCommitFile contains the integer passed as an argument.


**
** Otherwise return false.


*/
static void file_is_selected(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){


  assert(argc==1);
  if( g.aCommitFile ){
    int iId = sqlite3_value_int(argv[0]);
    int ii;
    for(ii=0; g.aCommitFile[ii]; ii++){
      if( iId==g.aCommitFile[ii] ){
        sqlite3_result_int(context, 1);
        return;
      }
    }




    sqlite3_result_int(context, 0);
  }else{



    sqlite3_result_int(context, 1);
  }
}

/*
** Convert the input string into an SHA1.  Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
................................................................................
LOCAL void db_connection_init(void){
  sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
  sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
  sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
  sqlite3_create_function(
    g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0



  );
  if( g.fSqlTrace ){
    sqlite3_trace(g.db, db_sql_trace, 0);
  }
}

/*
................................................................................
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );






    blob_reset(&localRoot);
  }

  db_swap_connections();

  blob_reset(&full);
}

/*
** COMMAND: open
**
** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
................................................................................
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local() ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path, 0);
  db_open_repository(blob_str(&path));





  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
                  " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
  if( vid==0 ){
    db_lset_int("checkout", 1);
................................................................................
  char const *def;      /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
  { "access-log",    0,                0, 0, "off"                 },
  { "allow-symlinks",0,                0, 1, "off"                 },
  { "auto-captcha",  "autocaptcha",    0, 0, "on"                  },

  { "auto-shun",     0,                0, 0, "on"                  },
  { "autosync",      0,                0, 0, "on"                  },
  { "binary-glob",   0,               32, 1, ""                    },
  { "clearsign",     0,                0, 0, "off"                 },
  { "case-sensitive",0,                0, 0, "on"                  },
  { "crnl-glob",     0,               16, 1, ""                    },
  { "default-perms", 0,               16, 0, "u"                   },
................................................................................
**                     (existing links in repository created on Unix become 
**                     plain-text files with link destination path inside).
**                     Default: off
**
**    auto-captcha     If enabled, the Login page provides a button to
**                     fill in the captcha password.  Default: on
**





**    auto-shun        If enabled, automatically pull the shunning list
**                     from a server to which the client autosyncs.
**                     Default: on
**
**    autosync         If enabled, automatically pull prior to commit
**                     or update and automatically push after commit or
**                     tag or branch creation.  If the value is "pullonly"







>
>
>







 







>










>
>
>
>
>
>
|
>







 







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







 







>
>
>
>
>
>
>







 







|







 







|

|
>

>
>
>
>
>
>
|
<
>
>

<
>
>






>
>
|





|
|


>
>
>
>
|

>
>
>
|







 







|
>
>
>







 







>
>
>
>
>
>

<
>
|
>







 







>
>
>
>
>
|
|







 







>







 







>
>
>
>
>







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
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
...
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
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
....
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
....
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
....
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
....
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
....
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
....
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
....
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
  int nPrepare;             /* Number of calls to sqlite3_prepare() */
  int nDeleteOnFail;        /* Number of entries in azDeleteOnFail[] */
  struct sCommitHook {
    int (*xHook)(void);         /* Functions to call at db_end_transaction() */
    int sequence;               /* Call functions in sequence order */
  } aHook[5];
  char *azDeleteOnFail[3];  /* Files to delete on a failure */
  char *azBeforeCommit[5];  /* Commands to run prior to COMMIT */
  int nBeforeCommit;        /* Number of entries in azBeforeCommit */
  int nPriorChanges;        /* sqlite3_total_changes() at transaction start */
} db = {0, 0, 0, 0, 0, 0, };

/*
** Arrange for the given file to be deleted on a failure.
*/
void db_delete_on_failure(const char *zFilename){
  assert( db.nDeleteOnFail<count(db.azDeleteOnFail) );
................................................................................
/*
** Begin and end a nested transaction
*/
void db_begin_transaction(void){
  if( db.nBegin==0 ){
    db_multi_exec("BEGIN");
    sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
    db.nPriorChanges = sqlite3_total_changes(g.db);
  }
  db.nBegin++;
}
void db_end_transaction(int rollbackFlag){
  if( g.db==0 ) return;
  if( db.nBegin<=0 ) return;
  if( rollbackFlag ) db.doRollback = 1;
  db.nBegin--;
  if( db.nBegin==0 ){
    int i;
    if( db.doRollback==0 && db.nPriorChanges<sqlite3_total_changes(g.db) ){
      while( db.nBeforeCommit ){
        db.nBeforeCommit--;
        sqlite3_exec(g.db, db.azBeforeCommit[db.nBeforeCommit], 0, 0, 0);
        sqlite3_free(db.azBeforeCommit[db.nBeforeCommit]);
      }
      leaf_do_pending_checks();
    }
    for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
      db.doRollback |= db.aHook[i].xHook();
    }
    while( db.pAllStmt ){
      db_finalize(db.pAllStmt);
    }
    db_multi_exec(db.doRollback ? "ROLLBACK" : "COMMIT");
................................................................................
  rc = sqlite3_exec(g.db, blob_buffer(&sql), 0, 0, &zErr);
  if( rc!=SQLITE_OK ){
    db_err("%s\n%s", zErr, blob_buffer(&sql));
  }
  blob_reset(&sql);
  return rc;
}

/*
** Optionally make the following changes to the database if feasible and
** convenient.  Do not start a transaction for these changes, but only
** make these changes if other changes are also being made.
*/
void db_optional_sql(const char *zDb, const char *zSql, ...){
  if( db_is_writeable(zDb) && db.nBeforeCommit < count(db.azBeforeCommit) ){
    va_list ap;
    va_start(ap, zSql);
    db.azBeforeCommit[db.nBeforeCommit++] = sqlite3_vmprintf(zSql, ap);
    va_end(ap);
  }
}

/*
** Execute a query and return a single integer value.
*/
i64 db_int64(i64 iDflt, const char *zSql, ...){
  va_list ap;
  Stmt s;
................................................................................
** Return TRUE if the schema is out-of-date
*/
int db_schema_is_outofdate(void){
  return db_exists("SELECT 1 FROM config"
                   " WHERE name='aux-schema'"
                   "   AND value<>'%s'", AUX_SCHEMA);
}

/*
** Return true if the database is writeable
*/
int db_is_writeable(const char *zName){
  return g.db!=0 && !sqlite3_db_readonly(g.db, db_name(zName));
}

/*
** Verify that the repository schema is correct.  If it is not correct,
** issue a fatal error and die.
*/
void db_verify_schema(void){
  if( db_schema_is_outofdate() ){
................................................................................


/*
** Open the local database.  If unable, exit with an error.
*/
void db_must_be_within_tree(void){
  if( db_open_local()==0 ){
    fossil_fatal("current directory is not within an open checkout");
  }
  db_open_repository(0);
  db_verify_schema();
}

/*
** Close the database connection.
................................................................................
  }else if( argc==2 ){
    zP = (const char*)sqlite3_value_text(argv[1]);
    if( zP ) sqlite3_result_text(context, zP, -1, SQLITE_TRANSIENT);
  }
}

/*
** SQL function:
**
**       is_selected(id)
**       if_selected(id, X, Y)
**
** On the commit command, when filenames are specified (in order to do
** a partial commit) the vfile.id values for the named files are loaded
** into the g.aCommitFile[] array.  This function looks at that array
** to see if a file is named on the command-line.
**
** In the first form (1 argument) return TRUE if either no files are
** named on the command line (g.aCommitFile is NULL meaning that all

** changes are to be committed) or if id is found in g.aCommitFile[]
** (meaning that id was named on the command-line).
**

** In the second form (3 arguments) return argument X if true and Y
** if false.  Except if Y is NULL then always return X.
*/
static void file_is_selected(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  int rc = 0;

  assert(argc==1 || argc==3);
  if( g.aCommitFile ){
    int iId = sqlite3_value_int(argv[0]);
    int ii;
    for(ii=0; g.aCommitFile[ii]; ii++){
      if( iId==g.aCommitFile[ii] ){
        rc = 1;
        break;
      }
    }
  }else{
    rc = 1;
  }
  if( argc==1 ){
    sqlite3_result_int(context, rc);
  }else{
    assert( argc==3 );
    assert( rc==0 || rc==1 );
    if( sqlite3_value_type(argv[2-rc])==SQLITE_NULL ) rc = 1-rc;
    sqlite3_result_value(context, argv[2-rc]);
  }
}

/*
** Convert the input string into an SHA1.  Make a notation in the
** CONCEALED table so that the hash can be undo using the db_reveal()
** function at some later time.
................................................................................
LOCAL void db_connection_init(void){
  sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
  sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
  sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
  sqlite3_create_function(
    g.db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
  );
  sqlite3_create_function(
    g.db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
  );
  if( g.fSqlTrace ){
    sqlite3_trace(g.db, db_sql_trace, 0);
  }
}

/*
................................................................................
    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );
    db_swap_connections();
    db_optional_sql("repository", 
        "REPLACE INTO config(name,value,mtime)"
        "VALUES('ckout:%q',1,now())",
        blob_str(&localRoot)
    );
    blob_reset(&localRoot);

  }else{
    db_swap_connections();
  }
  blob_reset(&full);
}

/*
** COMMAND: open
**
** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
................................................................................
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local() ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path, 0);
  db_open_repository(blob_str(&path));
#if defined(_WIN32)
# define LOCALDB_NAME "./_FOSSIL_"
#else
# define LOCALDB_NAME "./.fslckout"
#endif
  db_init_database(LOCALDB_NAME, zLocalSchema, (char*)0);
  db_delete_on_failure(LOCALDB_NAME);
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
                  " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
  if( vid==0 ){
    db_lset_int("checkout", 1);
................................................................................
  char const *def;      /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
  { "access-log",    0,                0, 0, "off"                 },
  { "allow-symlinks",0,                0, 1, "off"                 },
  { "auto-captcha",  "autocaptcha",    0, 0, "on"                  },
  { "auto-hyperlink",0,                0, 0, "on",                 },
  { "auto-shun",     0,                0, 0, "on"                  },
  { "autosync",      0,                0, 0, "on"                  },
  { "binary-glob",   0,               32, 1, ""                    },
  { "clearsign",     0,                0, 0, "off"                 },
  { "case-sensitive",0,                0, 0, "on"                  },
  { "crnl-glob",     0,               16, 1, ""                    },
  { "default-perms", 0,               16, 0, "u"                   },
................................................................................
**                     (existing links in repository created on Unix become 
**                     plain-text files with link destination path inside).
**                     Default: off
**
**    auto-captcha     If enabled, the Login page provides a button to
**                     fill in the captcha password.  Default: on
**
**    auto-hyperlink   Use javascript to enable hyperlinks on web pages
**                     for all users (regardless of the "h" privilege) if the
**                     User-Agent string in the HTTP header look like it came
**                     from real person, not a spider or bot.  Default: on
**
**    auto-shun        If enabled, automatically pull the shunning list
**                     from a server to which the client autosyncs.
**                     Default: on
**
**    autosync         If enabled, automatically pull prior to commit
**                     or update and automatically push after commit or
**                     tag or branch creation.  If the value is "pullonly"

Changes to src/descendants.c.

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
...
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
*/
void compute_ancestors(int rid, int N){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;
  bag_init(&seen);
  pqueue_init(&queue);
  bag_insert(&seen, rid);
  pqueue_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q,
    "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
    " WHERE a.cid=:rid"
  );
  while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueue_insert(&queue, pid, -mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueue_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** Compute up to N direct ancestors (merge ancestors do not count)
** for the check-in rid and put them in a table named "ancestor".
................................................................................
void compute_descendants(int rid, int N){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;

  bag_init(&seen);
  pqueue_init(&queue);
  bag_insert(&seen, rid);
  pqueue_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid");
  while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueue_insert(&queue, pid, mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueue_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** COMMAND: descendants*
**







|

|





|








|





|







 







|

|


|








|





|







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
...
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
*/
void compute_ancestors(int rid, int N){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;
  bag_init(&seen);
  pqueuex_init(&queue);
  bag_insert(&seen, rid);
  pqueuex_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q,
    "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
    " WHERE a.cid=:rid"
  );
  while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueuex_insert(&queue, pid, -mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueuex_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** Compute up to N direct ancestors (merge ancestors do not count)
** for the check-in rid and put them in a table named "ancestor".
................................................................................
void compute_descendants(int rid, int N){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;

  bag_init(&seen);
  pqueuex_init(&queue);
  bag_insert(&seen, rid);
  pqueuex_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid");
  while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueuex_insert(&queue, pid, mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueuex_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** COMMAND: descendants*
**

Changes to src/diff.c.

375
376
377
378
379
380
381
382
383
384



385
386
387
388
389
390
391
...
431
432
433
434
435
436
437

438
439
440
441
442
443
444
...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
....
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
....
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
/*
** Flags for sbsWriteText()
*/
#define SBS_NEWLINE      0x0001   /* End with \n\000 */
#define SBS_PAD          0x0002   /* Pad output to width spaces */

/*
** Write up to width characters of pLine into z[].  Translate tabs into
** spaces.  Add a newline if SBS_NEWLINE is set.  Translate HTML characters
** if SBS_HTML is set.  Pad the rendering out width bytes if SBS_PAD is set.



*/
static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){
  int n = pLine->h & LENGTH_MASK;
  int i;   /* Number of input characters consumed */
  int j;   /* Number of output characters generated */
  int k;   /* Cursor position */
  int needEndSpan = 0;
................................................................................
      memcpy(&z[j], "&amp;", 5);
      j += 5;
    }else if( c=='>' && p->escHtml ){
      memcpy(&z[j], "&gt;", 4);
      j += 4;
    }else{
      z[j++] = c;

    }
  }
  if( needEndSpan ){
    memcpy(&z[j], "</span>", 7);
    j += 7;
  }
  if( (flags & SBS_PAD)!=0 ){
................................................................................
  int i, j;     /* Loop counters */
  int m, ma, mb;/* Number of lines to output */
  int skip;     /* Number of lines to skip */
  int nChunk = 0; /* Number of chunks of diff output seen so far */
  SbsLine s;    /* Output line buffer */

  memset(&s, 0, sizeof(s));
  s.zLine = fossil_malloc( 10*width + 200 );
  if( s.zLine==0 ) return;
  s.width = width;
  s.escHtml = escHtml;
  s.iStart = -1;
  s.iStart2 = 0;
  s.iEnd = -1;
  A = p->aFrom;
................................................................................
    score = (iEX - iSX) - 0.05*skew - 0.05*dist;
    if( score>bestScore ){
      bestScore = score;
      iSXb = iSX;
      iSYb = iSY;
      iEXb = iEX;
      iEYb = iEY;
    }else{
      iSXp = iSX;
      iSYp = iSY;
      iEXp = iEX;
      iEYp = iEY;
    }
  }
  if( iSXb==iEXb && (iE1-iS1)*(iE2-iS2)<400 ){
................................................................................
    const char *zUuidFile = db_column_text(&q, 2);
    const char *zUuidParentFile = db_column_text(&q, 3);
    const char *zDate = db_column_text(&q, 4);
    const char *zUser = db_column_text(&q, 5);
    if( webLabel ){
      if (zUuidParentFile) {
        zLabel = mprintf(
            "<a href='%s/info/%s' %s>%.10s</a> "
            "<a href='%s/fdiff?v1=%s&v2=%s' %s>d</a> "
            "%s %13.13s", 
            g.zTop, zUuid, zInfoTarget, zUuid,
            g.zTop, zUuidParentFile, zUuidFile, zDiffTarget,
            zDate, zUser);
      }else{
        zLabel = mprintf(
            "<a href='%s/info/%s' %s>%.10s</a>   "
            "%s %13.13s", 
            g.zTop, zUuid, zInfoTarget, zUuid,
            zDate, zUser);
      }
    }else{
      zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
    }
    p->nVers++;
    p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
................................................................................
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","-1"));
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");
  if( P("filevers") ) annFlags |= ANN_FILE_VERS;
  annotate_file(&ann, P("filename"), fnid, mid, g.perm.History, iLimit, annFlags);
  if( P("log") ){
    int i;
    @ <h2>Versions analyzed:</h2>
    @ <ol>
    for(i=0; i<ann.nVers; i++){
      @ <li><tt>%s(ann.azVers[i])</tt></li>
    }







|


>
>
>







 







>







 







|







 







|







 







|
|

|
|



|

|







 







|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
....
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
....
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
....
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
/*
** Flags for sbsWriteText()
*/
#define SBS_NEWLINE      0x0001   /* End with \n\000 */
#define SBS_PAD          0x0002   /* Pad output to width spaces */

/*
** Write up to width characters of pLine into p->zLine[].  Translate tabs into
** spaces.  Add a newline if SBS_NEWLINE is set.  Translate HTML characters
** if SBS_HTML is set.  Pad the rendering out width bytes if SBS_PAD is set.
**
** This comment contains multibyte unicode characters (ü, Æ, ð) in order
** to test the ability of the diff code to handle such characters.
*/
static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){
  int n = pLine->h & LENGTH_MASK;
  int i;   /* Number of input characters consumed */
  int j;   /* Number of output characters generated */
  int k;   /* Cursor position */
  int needEndSpan = 0;
................................................................................
      memcpy(&z[j], "&amp;", 5);
      j += 5;
    }else if( c=='>' && p->escHtml ){
      memcpy(&z[j], "&gt;", 4);
      j += 4;
    }else{
      z[j++] = c;
      if( (c&0xc0)==0x80 ) k--;
    }
  }
  if( needEndSpan ){
    memcpy(&z[j], "</span>", 7);
    j += 7;
  }
  if( (flags & SBS_PAD)!=0 ){
................................................................................
  int i, j;     /* Loop counters */
  int m, ma, mb;/* Number of lines to output */
  int skip;     /* Number of lines to skip */
  int nChunk = 0; /* Number of chunks of diff output seen so far */
  SbsLine s;    /* Output line buffer */

  memset(&s, 0, sizeof(s));
  s.zLine = fossil_malloc( 15*width + 200 );
  if( s.zLine==0 ) return;
  s.width = width;
  s.escHtml = escHtml;
  s.iStart = -1;
  s.iStart2 = 0;
  s.iEnd = -1;
  A = p->aFrom;
................................................................................
    score = (iEX - iSX) - 0.05*skew - 0.05*dist;
    if( score>bestScore ){
      bestScore = score;
      iSXb = iSX;
      iSYb = iSY;
      iEXb = iEX;
      iEYb = iEY;
    }else if( iEX>iEXp ){
      iSXp = iSX;
      iSYp = iSY;
      iEXp = iEX;
      iEYp = iEY;
    }
  }
  if( iSXb==iEXb && (iE1-iS1)*(iE2-iS2)<400 ){
................................................................................
    const char *zUuidFile = db_column_text(&q, 2);
    const char *zUuidParentFile = db_column_text(&q, 3);
    const char *zDate = db_column_text(&q, 4);
    const char *zUser = db_column_text(&q, 5);
    if( webLabel ){
      if (zUuidParentFile) {
        zLabel = mprintf(
            "<a href='%R/info/%s' %s>%.10s</a> "
            "<a href='%R/fdiff?v1=%s&v2=%s' %s>d</a> "
            "%s %13.13s", 
            zUuid, zInfoTarget, zUuid,
            zUuidParentFile, zUuidFile, zDiffTarget,
            zDate, zUser);
      }else{
        zLabel = mprintf(
            "<a href='%R/info/%s' %s>%.10s</a>   "
            "%s %13.13s", 
            zUuid, zInfoTarget, zUuid,
            zDate, zUser);
      }
    }else{
      zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
    }
    p->nVers++;
    p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
................................................................................
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","-1"));
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");
  if( P("filevers") ) annFlags |= ANN_FILE_VERS;
  annotate_file(&ann, P("filename"), fnid, mid, g.perm.Hyperlink, iLimit, annFlags);
  if( P("log") ){
    int i;
    @ <h2>Versions analyzed:</h2>
    @ <ol>
    for(i=0; i<ann.nVers; i++){
      @ <li><tt>%s(ann.azVers[i])</tt></li>
    }

Changes to src/diffcmd.c.

486
487
488
489
490
491
492

493
494
495
496
497
498
499
...
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
...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
**
** The "-N" or "--new-file" option causes the complete text of added or
** deleted files to be displayed.
**
** Options:

**   --brief             Show filenames only
**   --context|-c N      Use N lines of context 
**   --from|-r VERSION   select VERSION as source for the diff
**   -i                  use internal diff logic
**   --new-file|-N       output complete text of added or deleted files
**   --to VERSION        select VERSION as target for the diff
**   --side-by-side|-y   side-by-side diff
................................................................................
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */
  int hasNFlag;              /* True if -N or --new-file flag is used */
  const char *zFrom;         /* Source version number */
  const char *zTo;           /* Target version number */

  const char *zDiffCmd = 0;  /* External diff command. NULL for internal diff */
  int diffFlags = 0;         /* Flags to control the DIFF */
  int f;

  isGDiff = g.argv[1][0]=='g';
  isInternDiff = find_option("internal","i",0)!=0;
  zFrom = find_option("from", "r", 1);
  zTo = find_option("to", 0, 1);

  diffFlags = diff_options();
  hasNFlag = find_option("new-file","N",0)!=0;
  if( hasNFlag ) diffFlags |= DIFF_NEWFILE;








  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc>=3 ){
................................................................................
      diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
    }
  }
}

/*
** WEBPAGE: vpatch
** URL vpatch?from=UUID&amp;to=UUID
*/
void vpatch_page(void){
  const char *zFrom = P("from");
  const char *zTo = P("to");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( zFrom==0 || zTo==0 ) fossil_redirect_home();

  cgi_set_content_type("text/plain");
  diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE);
}







>







 







>








>




>
>
>
>
>
>
>







 







|











486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
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
...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
** the "setting" command.  If no external diff program is configured, then
** the "-i" option is a no-op.  The "-i" option converts "gdiff" into "diff".
**
** The "-N" or "--new-file" option causes the complete text of added or
** deleted files to be displayed.
**
** Options:
**   --branch BRANCH     Show diff of all changes on BRANCH
**   --brief             Show filenames only
**   --context|-c N      Use N lines of context 
**   --from|-r VERSION   select VERSION as source for the diff
**   -i                  use internal diff logic
**   --new-file|-N       output complete text of added or deleted files
**   --to VERSION        select VERSION as target for the diff
**   --side-by-side|-y   side-by-side diff
................................................................................
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */
  int hasNFlag;              /* True if -N or --new-file flag is used */
  const char *zFrom;         /* Source version number */
  const char *zTo;           /* Target version number */
  const char *zBranch;       /* Branch to diff */
  const char *zDiffCmd = 0;  /* External diff command. NULL for internal diff */
  int diffFlags = 0;         /* Flags to control the DIFF */
  int f;

  isGDiff = g.argv[1][0]=='g';
  isInternDiff = find_option("internal","i",0)!=0;
  zFrom = find_option("from", "r", 1);
  zTo = find_option("to", 0, 1);
  zBranch = find_option("branch", 0, 1);
  diffFlags = diff_options();
  hasNFlag = find_option("new-file","N",0)!=0;
  if( hasNFlag ) diffFlags |= DIFF_NEWFILE;

  if( zBranch ){
    if( zTo || zFrom ){
      fossil_fatal("cannot use --from or --to with --branch");
    }
    zTo = zBranch;
    zFrom = mprintf("root:%s", zBranch);
  }
  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc>=3 ){
................................................................................
      diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
    }
  }
}

/*
** WEBPAGE: vpatch
** URL vpatch?from=UUID&to=UUID
*/
void vpatch_page(void){
  const char *zFrom = P("from");
  const char *zTo = P("to");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( zFrom==0 || zTo==0 ) fossil_redirect_home();

  cgi_set_content_type("text/plain");
  diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE);
}

Changes to src/event.c.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46
47
48
49
50
51
52
...
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
#include "event.h"

/*
** Output a hyperlink to an event given its tagid.
*/
void hyperlink_to_event_tagid(int tagid){
  char *zEventId;
  char zShort[12];

  zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
                     tagid);
  sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
  if( g.perm.History ){
    @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
  }else{
    @ [%s(zShort)]
  }

  free(zEventId);
}

/*
** WEBPAGE: event
** URL: /event
** PARAMETERS:
................................................................................
  if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
    style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
                          g.zTop, zEventId);
  }
  zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
  style_submenu_element("Context", "Context", "%s/timeline?c=%T",
                        g.zTop, zETime);
  if( g.perm.History ){
    if( showDetail ){
      style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
                            g.zTop, zEventId, zUuid);
      if( nextRid ){
        char *zNext;
        zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
        style_submenu_element("Next", "Next",
                              "%s/event?name=%s&amp;aid=%s&amp;detail=1",
                              g.zTop, zEventId, zNext);
        free(zNext);
      }
      if( prevRid ){
        char *zPrev;
        zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
        style_submenu_element("Prev", "Prev",
                              "%s/event?name=%s&amp;aid=%s&amp;detail=1",
                              g.zTop, zEventId, zPrev);
        free(zPrev);
      }
    }else{
      style_submenu_element("Detail", "Detail",
                            "%s/event?name=%s&amp;aid=%s&amp;detail=1",
                            g.zTop, zEventId, zUuid);
    }
  }

  if( showDetail && g.perm.History ){
    int i;
    const char *zClr = 0;
    Blob comment;

    zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
    @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at
    @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>]
    @ entered by user <b>%h(pEvent->zUser)</b> on
    @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p>
    @ <blockquote>
    for(i=0; i<pEvent->nTag; i++){
      if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
        zClr = pEvent->aTag[i].zValue;
      }
    }
    if( zClr && zClr[0]==0 ) zClr = 0;







<
<


<
<
<
<
<
<
>







 







|

|





|







|





|




|





|
|

|







29
30
31
32
33
34
35


36
37






38
39
40
41
42
43
44
45
...
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
#include "event.h"

/*
** Output a hyperlink to an event given its tagid.
*/
void hyperlink_to_event_tagid(int tagid){
  char *zEventId;


  zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
                     tagid);






  @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>]
  free(zEventId);
}

/*
** WEBPAGE: event
** URL: /event
** PARAMETERS:
................................................................................
  if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){
    style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s",
                          g.zTop, zEventId);
  }
  zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
  style_submenu_element("Context", "Context", "%s/timeline?c=%T",
                        g.zTop, zETime);
  if( g.perm.Hyperlink ){
    if( showDetail ){
      style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s",
                            g.zTop, zEventId, zUuid);
      if( nextRid ){
        char *zNext;
        zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
        style_submenu_element("Next", "Next",
                              "%s/event?name=%s&aid=%s&detail=1",
                              g.zTop, zEventId, zNext);
        free(zNext);
      }
      if( prevRid ){
        char *zPrev;
        zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
        style_submenu_element("Prev", "Prev",
                              "%s/event?name=%s&aid=%s&detail=1",
                              g.zTop, zEventId, zPrev);
        free(zPrev);
      }
    }else{
      style_submenu_element("Detail", "Detail",
                            "%s/event?name=%s&aid=%s&detail=1",
                            g.zTop, zEventId, zUuid);
    }
  }

  if( showDetail && g.perm.Hyperlink ){
    int i;
    const char *zClr = 0;
    Blob comment;

    zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
    @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at
    @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
    @ entered by user <b>%h(pEvent->zUser)</b> on
    @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
    @ <blockquote>
    for(i=0; i<pEvent->nTag; i++){
      if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
        zClr = pEvent->aTag[i].zValue;
      }
    }
    if( zClr && zClr[0]==0 ) zClr = 0;

Changes to src/finfo.c.

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
      @ <tr><td>
      @   <div class="divider">%s(zPrevDate)</div>
      @ </td></tr>
    }
    memcpy(zTime, &zDate[11], 5);
    zTime[5] = 0;
    @ <tr><td class="timelineTime">
    @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
    }else{
      @ <td class="timelineTableCell">
    }
    sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
    sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
    if( zUuid ){
      if( g.perm.History ){
        @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
      }else{
        @ [%S(zUuid)]
      }
      @ part of check-in
    }else{
      @ <b>Deleted</b> by check-in
    }
    hyperlink_to_uuid(zShortCkin);
    @ %h(zCom) (user: 
    hyperlink_to_user(zUser, zDate, "");
    @ branch: %h(zBr))
    if( g.perm.History && zUuid ){
      const char *z = zFilename;
      if( fpid ){
        @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
      }
      @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
      @ [annotate]</a>
    }
    @ </td></tr>
  }
  db_finalize(&q);
  if( pGraph ){
    graph_finish(pGraph, 0);







|









<
<
<
<
<
|







|


|

|







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
      @ <tr><td>
      @   <div class="divider">%s(zPrevDate)</div>
      @ </td></tr>
    }
    memcpy(zTime, &zDate[11], 5);
    zTime[5] = 0;
    @ <tr><td class="timelineTime">
    @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
    }else{
      @ <td class="timelineTableCell">
    }
    sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
    sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
    if( zUuid ){





      @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in
    }else{
      @ <b>Deleted</b> by check-in
    }
    hyperlink_to_uuid(zShortCkin);
    @ %h(zCom) (user: 
    hyperlink_to_user(zUser, zDate, "");
    @ branch: %h(zBr))
    if( g.perm.Hyperlink && zUuid ){
      const char *z = zFilename;
      if( fpid ){
        @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
      }
      @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
      @ [annotate]</a>
    }
    @ </td></tr>
  }
  db_finalize(&q);
  if( pGraph ){
    graph_finish(pGraph, 0);

Changes to src/glob.c.

108
109
110
111
112
113
114
115


116
117
118
119
120
121
122
  if( zPatternList==0 || zPatternList[0]==0 ) return 0;
  nList = strlen(zPatternList);
  p = fossil_malloc( sizeof(*p) + nList+1 );
  memset(p, 0, sizeof(*p));
  z = (char*)&p[1];
  memcpy(z, zPatternList, nList+1);
  while( z[0] ){
    while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ) z++;  /* Skip leading spaces and newlines */


    if( z[0]=='\'' || z[0]=='"' ){
      delimiter = z[0];
      z++;
    }else{
      delimiter = ',';
    }
    if( z[0]==0 ) break;







|
>
>







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  if( zPatternList==0 || zPatternList[0]==0 ) return 0;
  nList = strlen(zPatternList);
  p = fossil_malloc( sizeof(*p) + nList+1 );
  memset(p, 0, sizeof(*p));
  z = (char*)&p[1];
  memcpy(z, zPatternList, nList+1);
  while( z[0] ){
    while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ){
      z++;  /* Skip leading spaces and newlines */
    }
    if( z[0]=='\'' || z[0]=='"' ){
      delimiter = z[0];
      z++;
    }else{
      delimiter = ',';
    }
    if( z[0]==0 ) break;

Changes to src/info.c.

119
120
121
122
123
124
125
































126
127
128
129
130
131
132
...
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
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
...
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
...
442
443
444
445
446
447
448

449
450
451
452
453
454
455
456
457



458
459
460
461
462
463
464
...
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
...
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
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
...
719
720
721
722
723
724
725


726



727
728
729
730
731
732
733
...
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
...
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
...
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
....
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
....
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
....
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
....
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
....
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
....
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
....
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
....
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
....
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
....
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
....
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
....
1940
1941
1942
1943
1944
1945
1946




1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
....
1965
1966
1967
1968
1969
1970
1971







1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994

1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013

2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
  if( zComment ){
    fossil_print("comment:      ");
    comment_print(zComment, 14, 79);
    free(zComment);
  }
}


































/*
** COMMAND: info
**
** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
**
** With no arguments, provide information about the current tree.
................................................................................
**
** Use the "finfo" command to get information about a specific
** file in a checkout.
**
** Options:
**
**    -R|--repository FILE       Extract info from repository FILE

**
** See also: annotate, artifact, finfo, timeline
*/
void info_cmd(void){
  i64 fsize;

  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));

    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_repository_filename());
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }

#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif
    fossil_print("project-code: %s\n", db_get("project-code", ""));
    vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
................................................................................
        hyperlink_to_uuid(zOrigUuid);
      }else{
        @ propagates to descendants
      }
#if 0
      if( zValue && fossil_strcmp(zTagname,"branch")==0 ){
        @ &nbsp;&nbsp;
        @ <a href="%s(g.zTop)/timeline?r=%T(zValue)">branch timeline</a>
      }
#endif
    }
    if( zSrcUuid && zSrcUuid[0] ){
      if( tagtype==0 ){
        @ by
      }else{
................................................................................
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int diffFlags,        /* Flags for text_diff().  Zero to omit diffs */
  int mperm             /* executable or symlink permission for zNew */
){
  if( !g.perm.History ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
................................................................................
      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>
    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
        @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
        @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ <p>Name change from
        @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a>
        @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>.
      }else{
        @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
        @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      }
    }else if( zOld ){
      @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
    }else{
      @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
    }
    if( diffFlags ){
      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
    }
    @ </p>
  }
}

/*
** Construct an appropriate diffFlag for text_diff() based on query
................................................................................
    const char *zUuid = db_column_text(&q, 0);
    char *zTitle = mprintf("Check-in [%.10s]", zUuid);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zComment;
    const char *zDate;
    const char *zOrigDate;

    style_header(zTitle);
    login_anonymous_available();
    free(zTitle);
    zEUser = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                    TAG_USER, rid);
    zEComment = db_text(0, 
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_COMMENT, rid);



    zUser = db_column_text(&q, 2);
    zComment = db_column_text(&q, 3);
    zDate = db_column_text(&q,1);
    zOrigDate = db_column_text(&q, 4);
    @ <div class="section">Overview</div>
    @ <table class="label-value">
    @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
................................................................................
        const char *zDate = db_column_text(&q, 2);
        if( zUser==0 || zUser[0]==0 ) zUser = "unknown";
        @ <tr><th>Received&nbsp;From:</th>
        @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
      }
      db_finalize(&q);
    }
    if( g.perm.History ){
      const char *zProjName = db_get("project-name", "unnamed");
      @ <tr><th>Timelines:</th><td>
      @   <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
      if( zParent ){
        @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
      }
      if( !isLeaf ){
        @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a>
      }
      if( zParent && !isLeaf ){
        @ | <a href="%s(g.zTop)/timeline?dp=%S(zUuid)">both</a>
      }
      db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
                     " WHERE rid=%d AND tagtype>0 "
                     "   AND tag.tagid=tagxref.tagid "
                     "   AND +tag.tagname GLOB 'sym-*'", rid);
      while( db_step(&q)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q, 0);
        @  | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a>
      }
      db_finalize(&q);
      @ </td></tr>
      @ <tr><th>Other&nbsp;Links:</th>
      @   <td>
      @     <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
      if( g.perm.Zip ){
        char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
                             g.zTop, zProjName, zUuid, zUuid);
        @ | <a href="%s(zUrl)">Tarball</a>
        @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">




        @         ZIP archive</a>
        fossil_free(zUrl);
      }


      @   | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>











      @   | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
      @           vdiff to parent branch</a>
      if( g.perm.Write ){
        @   | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
      }
      @   </td>
      @ </tr>
    }
    @ </table>
  }else{
    style_header("Check-in Information");
................................................................................
  if( zParent ){
    @ <div class="section">Changes</div>
    @ <div class="sectionmenu">
    showDiff = g.zPath[0]!='c';
    if( db_get_boolean("show-version-diffs", 0)==0 ){
      showDiff = !showDiff;
      if( showDiff ){
        @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)">
        @ hide&nbsp;diffs</a>
        if( sideBySide ){
          @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
          @ unified&nbsp;diffs</a>
        }else{
          @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
          @ side-by-side&nbsp;diffs</a>
        }
      }else{
        @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
        @ show&nbsp;unified&nbsp;diffs</a>
        @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
        @ show&nbsp;side-by-side&nbsp;diffs</a>
      }
    }else{
      if( showDiff ){
        @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide&nbsp;diffs</a>
        if( sideBySide ){
          @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=0">
          @ unified&nbsp;diffs</a>
        }else{
          @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=1">
          @ side-by-side&nbsp;diffs</a>
        }
      }else{
        @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=0">
        @ show&nbsp;unified&nbsp;diffs</a>
        @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=1">
        @ show&nbsp;side-by-side&nbsp;diffs</a>
      }
    }
    @ <a class="button" href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">
    @ patch</a></div>
    db_prepare(&q,
       "SELECT name,"
       "       mperm,"
       "       (SELECT uuid FROM blob WHERE rid=mlink.pid),"
       "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"
       "       (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
................................................................................
    @ <tr><th>Date:</th><td>
    hyperlink_to_date(zDate, "</td></tr>");
    if( g.perm.Setup ){
      @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
    }
    @ <tr><th>Original&nbsp;User:</th><td>
    hyperlink_to_user(zUser, zDate, "</td></tr>");
    if( g.perm.History ){
      @ <tr><th>Commands:</th>
      @   <td>
      @     <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
      @     | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
      @   </td>
      @ </tr>
    }
    @ </table></p>
  }else{
    style_header("Wiki Information");
    rid = 0;
................................................................................
** manifest.  Return the number of errors.
*/
static Manifest *vdiff_parse_manifest(const char *zParam, int *pRid){
  int rid;

  *pRid = rid = name_to_rid_www(zParam);
  if( rid==0 ){


    webpage_error("Missing \"%s\" query parameter.", zParam);



    return 0;
  }
  if( !is_a_version(rid) ){
    webpage_error("Artifact %s is not a checkin.", P(zParam));
    return 0;
  }
  return manifest_get(rid, CFTYPE_MANIFEST);
................................................................................
  }
  db_finalize(&q);
}


/*
** WEBPAGE: vdiff
** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN;sbs=BOOLEAN
**
** Show all differences between two checkins.  
*/
void vdiff_page(void){
  int ridFrom, ridTo;
  int showDetail = 0;
  int sideBySide = 0;
  int diffFlags = 0;
  Manifest *pFrom, *pTo;
  ManifestFile *pFileFrom, *pFileTo;


  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  login_anonymous_available();






  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;
  sideBySide = atoi(PD("sbs","1"));
  showDetail = atoi(PD("detail","0"));
  if( !showDetail && sideBySide ) showDetail = 1;
  if (showDetail){
    style_submenu_element("Abstract", "abstract",
                          "%s/vdiff?from=%T&to=%T&detail=0&sbs=0",
                          g.zTop, P("from"), P("to"));
................................................................................
      if( mPerm==PERM_LNK ){
        @ <li>Symbolic link
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
      }else{
        @ <li>File        
      }
      if( g.perm.History ){
        @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
      }else{
        @ %h(zName)
      }
      @ <ul>
      prevName = fossil_strdup(zName);
    }
    @ <li>
    hyperlink_to_date(zDate,"");
    @ - part of checkin
    hyperlink_to_uuid(zVers);
    if( zBr && zBr[0] ){
      if( g.perm.History ){
        @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
      }else{
        @ on branch %h(zBr)
      }
    }
    @ - %w(zCom) (user:
    hyperlink_to_user(zUser,zDate,"");
    @ )
    if( g.perm.History ){
      @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">

      @ [annotate]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
................................................................................
    const char *zDate = db_column_text(&q, 1);
    const char *zUser = db_column_text(&q, 2);
    if( cnt>0 ){
      @ Also wiki page
    }else{
      @ Wiki page
    }
    if( g.perm.History ){
      @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
    }else{
      @ [%h(zPagename)]
    }
    @ by
    hyperlink_to_user(zUser,zDate," on");
    hyperlink_to_date(zDate,".");
    nWiki++;
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%s.wiki", zPagename);
    }
................................................................................
    /* const char *zSrc = db_column_text(&q, 4); */
    if( cnt>0 ){
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      if( g.perm.History && g.perm.RdTkt ){
        @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
      }else{
        @ ticket [%S(zTarget)]
      }
    }else{
      if( g.perm.History && g.perm.RdWiki ){
        @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
      }else{
        @ wiki page [%h(zTarget)]
      }
    }
    @ added by
    hyperlink_to_user(zUser,zDate," on");
    hyperlink_to_date(zDate,".");
................................................................................
  }
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }
  }else if( linkToView && g.perm.History ){
    @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
  }
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
................................................................................
      style_submenu_element("Unified Diff", "udiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=0",
                            g.zTop, P("v1"), P("v2"));
    }

    if( P("smhdr")!=0 ){
      @ <h2>Differences From Artifact
      @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To
      @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2>
    }else{
      @ <h2>Differences From
      @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
      object_description(v1, 0, 0);
      @ <h2>To Artifact
      @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
      object_description(v2, 0, 0);
    }
    @ <hr />
    @ <div class="%s(zStyle)">
    @ %s(blob_str(&diff))
    @ </div>
    blob_reset(&diff);
................................................................................
  rid = name_to_rid_www("name");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  style_header("Hex Artifact Content");
................................................................................
    else cgi_append_content("\n", 1);
    z += i;
    if( z[0]=='\n' ) z++;
  }
  if( n<iEnd ) cgi_printf("</div>");
  @ </pre>
  if( iStart ){
    @ <script type="text/JavaScript">
    @ /* <![CDATA[ */
    @ document.getElementById('topln').scrollIntoView(true);
    @ /* ]]> */
    @ </script>
  }
}


/*
** WEBPAGE: artifact
** URL: /artifact/ARTIFACTID
................................................................................

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  style_header("Artifact Content");
................................................................................
        output_text_with_line_numbers(z, zLn);
      }else{
        @ <pre>
        @ %h(z)
        @ </pre>
      }
    }else if( strncmp(zMime, "image/", 6)==0 ){
      @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&amp;m=%s(zMime)"></img>
    }else{
      @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
    }
    @ </blockquote>
  }
  style_footer();
}  
................................................................................
  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(); return; }
  rid = name_to_rid_www("name");
  if( rid==0 ){ fossil_redirect_home(); }
  zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Admin ){
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  pTktChng = manifest_get(rid, CFTYPE_TICKET);
................................................................................
  if( pTktChng==0 ){
    fossil_redirect_home();
  }
  style_header("Ticket Change Details");
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, 10);
  zTktName[10] = 0;
  if( g.perm.History ){
    @ <h2>Changes to ticket
    @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
    @
    @ <p>By %h(pTktChng->zUser) on %s(zDate).  See also:
    @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
    @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket
    @ history</a></p>
  }else{
    @ <h2>Changes to ticket %s(zTktName)</h2>
    @
    @ <p>By %h(pTktChng->zUser) on %s(zDate).
    @ </p>
  }
  @
................................................................................
  };
  int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
  int stdClrFound = 0;
  int i;

  @ <table border="0" cellpadding="0" cellspacing="1">
  if( zIdPropagate ){
    @ <tr><td colspan="6" align="left">
    if( fPropagate ){
      @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" />
    }else{
      @ <input type="checkbox" name="%s(zIdPropagate)" />
    }
    @ Propagate color to descendants</td></tr>
  }
  @ <tr>
  for(i=0; i<nColor; i++){
    const char *zClr = aColor[i].zColor;
    if( zClr==0 ) zClr = aColor[i].zCName;
    if( zClr[0] ){
      @ <td style="background-color: %h(zClr);">
................................................................................
  const char *zNewTagFlag;
  const char *zNewTag;
  const char *zNewBrFlag;
  const char *zNewBranch;
  const char *zCloseFlag;
  int fPropagateColor;          /* True if color propagates before edit */
  int fNewPropagateColor;       /* True if color propagates after edit */

  char *zUuid;
  Blob comment;
  Stmt q;
  
  login_check_credentials();
  if( !g.perm.Write ){ login_needed(); return; }
  rid = name_to_typed_rid(P("r"), "ci");
................................................................................
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
                        "  FROM event WHERE objid=%d", rid);
  if( zComment==0 ) fossil_redirect_home();
  if( P("cancel") ){
    cgi_redirectf("ci?name=%s", zUuid);
  }

  zNewComment = PD("c",zComment);
  zUser = db_text(0, "SELECT coalesce(euser,user)"
                     "  FROM event WHERE objid=%d", rid);
  if( zUser==0 ) fossil_redirect_home();
  zNewUser = PDT("u",zUser);
  zDate = db_text(0, "SELECT datetime(mtime)"
                     "  FROM event WHERE objid=%d", rid);
................................................................................
  if( P("apply") ){
    Blob ctrl;
    char *zNow;
    int nChng = 0;

    login_verify_csrf_secret();
    blob_zero(&ctrl);
    zNow = date_in_standard_format("now");
    blob_appendf(&ctrl, "D %s\n", zNow);
    db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)");
    if( zNewColor[0]
     && (fPropagateColor!=fNewPropagateColor 
             || fossil_strcmp(zColor,zNewColor)!=0)
    ){
      char *zPrefix = "+";
................................................................................
      }
      nTag++;
    }
    db_finalize(&q);
    blob_appendf(&suffix, ")");
    @ %s(blob_str(&suffix))
    @ </td></tr></table>




    @ </blockquote>
    @ <hr />
    blob_reset(&suffix);
  }
  @ <p>Make changes to attributes of check-in
  @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
  @ <form action="%s(g.zTop)/ci_edit" method="post"><div>
  login_insert_csrf_secret();
  @ <input type="hidden" name="r" value="%S(zUuid)" />
  @ <table border="0" cellspacing="10">

  @ <tr><td align="right" valign="top"><b>User:</b></td>
  @ <td valign="top">
................................................................................
  @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea>
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td>
  @ <td valign="top">
  @   <input type="text" name="dt" size="20" value="%h(zNewDate)" />
  @ </td></tr>








  @ <tr><td align="right" valign="top"><b>Background Color:</b></td>
  @ <td valign="top">
  render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust");
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Tags:</b></td>
  @ <td valign="top">
  @ <input type="checkbox" name="newtag"%s(zNewTagFlag) />
  @ Add the following new tag name to this check-in:
  @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)" />

  db_prepare(&q,
     "SELECT tag.tagid, tagname FROM tagxref, tag"
     " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid"
     " ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)"
     "               ELSE tagname END /*sort*/",
     rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    int tagid = db_column_int(&q, 0);
    const char *zTagName = db_column_text(&q, 1);
    char zLabel[30];
    sqlite3_snprintf(sizeof(zLabel), zLabel, "c%d", tagid);

    if( P(zLabel) ){
      @ <br /><input type="checkbox" name="c%d(tagid)" checked="checked" />
    }else{
      @ <br /><input type="checkbox" name="c%d(tagid)" />
    }
    if( strncmp(zTagName, "sym-", 4)==0 ){
      @ Cancel tag <b>%h(&zTagName[4])</b>
    }else{
      @ Cancel special tag <b>%h(zTagName)</b>
    }
  }
  db_finalize(&q);
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Branching:</b></td>
  @ <td valign="top">
  @ <input type="checkbox" name="newbr"%s(zNewBrFlag) />
  @ Make this check-in the start of a new branch named:
  @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)" />

  @ </td></tr>

  if( is_a_leaf(rid)
   && !db_exists("SELECT 1 FROM tagxref "
                 " WHERE tagid=%d AND rid=%d AND tagtype>0",
                 TAG_CLOSED, rid)
  ){
    @ <tr><td align="right" valign="top"><b>Leaf Closure:</b></td>
    @ <td valign="top">
    @ <input type="checkbox" name="close"%s(zCloseFlag) />
    @ Mark this leaf as "closed" so that it no longer appears on the
    @ "leaves" page and is no longer labeled as a "<b>Leaf</b>".
    @ </td></tr>
  }


  @ <tr><td colspan="2">
  @ <input type="submit" name="preview" value="Preview" />
  @ <input type="submit" name="apply" value="Apply Changes" />
  @ <input type="submit" name="cancel" value="Cancel" />
  @ </td></tr>
  @ </table>
  @ </div></form>
  style_footer();
}







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







 







>





>






>












>







 







|







 







|







 







|
|
|


|
|


|


|
|

|
|







|







 







>









>
>
>







 







|


|

|


|


|







|


<
<
<
<

|
|
<
<
>
>
>
>



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



|







 







|


|


|



|

|




|

|


|



|

|



|







 







|


|
|







 







>
>
|
>
>
>







 







|










>





>
>
>
>
>
|
|
|
|







 







|
<
<
<
<








|
<
<
<
|
<

|
<
|
<
>







 







|
<
<
<
<
<







 







|
|




|
|







 







|
|







 







|
|


|

|
<







 







|







 







<
<
|
<
<







 







|







 







|







 







|







 







|

|


|
|
<







 







|





|







 







>







 







>







 







|







 







>
>
>
>





|







 







>
>
>
>
>
>
>








|
|
|
>












>

|

|


|

|







|
|
|
>









|

|













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
...
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
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
...
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
...
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
...
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
...
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
...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
...
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
...
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
...
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
....
1022
1023
1024
1025
1026
1027
1028
1029





1030
1031
1032
1033
1034
1035
1036
....
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
....
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
....
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
....
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
....
1402
1403
1404
1405
1406
1407
1408


1409


1410
1411
1412
1413
1414
1415
1416
....
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
....
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
....
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
1565
....
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
....
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
....
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
....
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
....
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
....
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
  if( zComment ){
    fossil_print("comment:      ");
    comment_print(zComment, 14, 79);
    free(zComment);
  }
}

/*
** Print information about the URLs used to access a repository and
** checkouts in a repository.
*/
static void extraRepoInfo(void){
  Stmt s;
  db_prepare(&s, "SELECT substr(name,7), date(mtime,'unixepoch')"
                 "  FROM config"
                 " WHERE name GLOB 'ckout:*' ORDER BY name");
  while( db_step(&s)==SQLITE_ROW ){
    const char *zName;
    const char *zCkout = db_column_text(&s, 0);
    if( g.localOpen ){
      if( fossil_strcmp(zCkout, g.zLocalRoot)==0 ) continue;
      zName = "alt-root:";
    }else{
      zName = "check-out:";
    }
    fossil_print("%-11s   %-54s %s\n", zName, zCkout,
                 db_column_text(&s, 1));
  }
  db_finalize(&s);
  db_prepare(&s, "SELECT substr(name,9), date(mtime,'unixepoch')"
                 "  FROM config"
                 " WHERE name GLOB 'baseurl:*' ORDER BY name");
  while( db_step(&s)==SQLITE_ROW ){
    fossil_print("access-url:   %-54s %s\n", db_column_text(&s, 0),
                 db_column_text(&s, 1));
  }
  db_finalize(&s);
}


/*
** COMMAND: info
**
** Usage: %fossil info ?VERSION | REPOSITORY_FILENAME? ?OPTIONS?
**
** With no arguments, provide information about the current tree.
................................................................................
**
** Use the "finfo" command to get information about a specific
** file in a checkout.
**
** Options:
**
**    -R|--repository FILE       Extract info from repository FILE
**    -l|--detail                Show extra information
**
** See also: annotate, artifact, finfo, timeline
*/
void info_cmd(void){
  i64 fsize;
  int bDetail = find_option("detail","l",0)!=0;
  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
    extraRepoInfo();
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_repository_filename());
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }
    if( bDetail ) extraRepoInfo();
#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif
    fossil_print("project-code: %s\n", db_get("project-code", ""));
    vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
................................................................................
        hyperlink_to_uuid(zOrigUuid);
      }else{
        @ propagates to descendants
      }
#if 0
      if( zValue && fossil_strcmp(zTagname,"branch")==0 ){
        @ &nbsp;&nbsp;
        @ %z(href("%R/timeline?r=%T",zValue))branch timeline</a>
      }
#endif
    }
    if( zSrcUuid && zSrcUuid[0] ){
      if( tagtype==0 ){
        @ by
      }else{
................................................................................
  const char *zName,    /* Name of the file that has changed */
  const char *zOld,     /* blob.uuid before change.  NULL for added files */
  const char *zNew,     /* blob.uuid after change.  NULL for deletes */
  const char *zOldName, /* Prior name.  NULL if no name change. */
  int diffFlags,        /* Flags for text_diff().  Zero to omit diffs */
  int mperm             /* executable or symlink permission for zNew */
){
  if( !g.perm.Hyperlink ){
    if( zNew==0 ){
      @ <p>Deleted %h(zName)</p>
    }else if( zOld==0 ){
      @ <p>Added %h(zName)</p>
    }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
      @ <p>Name change from %h(zOldName) to %h(zName)
    }else if( fossil_strcmp(zNew, zOld)==0 ){
................................................................................
      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>
    }
  }else{
    if( zOld && zNew ){
      if( fossil_strcmp(zOld, zNew)!=0 ){
        @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
        @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
        @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
      }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
        @ <p>Name change from
        @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
        @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
      }else{
        @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
        @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
      }
    }else if( zOld ){
      @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a>
      @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
    }else{
      @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
      @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
    }
    if( diffFlags ){
      @ <pre style="white-space:pre;">
      append_diff(zOld, zNew, diffFlags);
      @ </pre>
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
    }
    @ </p>
  }
}

/*
** Construct an appropriate diffFlag for text_diff() based on query
................................................................................
    const char *zUuid = db_column_text(&q, 0);
    char *zTitle = mprintf("Check-in [%.10s]", zUuid);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zComment;
    const char *zDate;
    const char *zOrigDate;
    const char *zBranch;
    style_header(zTitle);
    login_anonymous_available();
    free(zTitle);
    zEUser = db_text(0,
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                    TAG_USER, rid);
    zEComment = db_text(0, 
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_COMMENT, rid);
    zBranch = db_text("trunk",
                   "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
                   TAG_BRANCH, rid);
    zUser = db_column_text(&q, 2);
    zComment = db_column_text(&q, 3);
    zDate = db_column_text(&q,1);
    zOrigDate = db_column_text(&q, 4);
    @ <div class="section">Overview</div>
    @ <table class="label-value">
    @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
................................................................................
        const char *zDate = db_column_text(&q, 2);
        if( zUser==0 || zUser[0]==0 ) zUser = "unknown";
        @ <tr><th>Received&nbsp;From:</th>
        @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
      }
      db_finalize(&q);
    }
    if( g.perm.Hyperlink ){
      const char *zProjName = db_get("project-name", "unnamed");
      @ <tr><th>Timelines:</th><td>
      @   %z(href("%R/timeline?f=%S",zUuid))family</a>
      if( zParent ){
        @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
      }
      if( !isLeaf ){
        @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a>
      }
      if( zParent && !isLeaf ){
        @ | %z(href("%R/timeline?dp=%S",zUuid))both</a>
      }
      db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
                     " WHERE rid=%d AND tagtype>0 "
                     "   AND tag.tagid=tagxref.tagid "
                     "   AND +tag.tagname GLOB 'sym-*'", rid);
      while( db_step(&q)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q, 0);
        @  | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
      }
      db_finalize(&q);




      if( g.perm.Zip ){
        char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s",
                             zProjName, zUuid, zUuid);


        @ </td></tr>
        @ <tr><th>Downloads:</th><td>
        @ %z(href("%s",zUrl))Tarball</a>
        @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
        @         ZIP archive</a>
        fossil_free(zUrl);
      }
#if 0
      if( isLeaf && fossil_strcmp(zBranch,"trunk")!=0 ){
        @ </td></tr>
        @ <tr><th>Diffs:</th><td>
        @ %z(href("%R/vdiff?branch=%t",zBranch))Changes in %h(zBranch)</a>
        @ | %z(href("%R/vdiff?from=trunk&to=%t",zBranch))Changes
        @         from trunk</a>
      }
#endif
      @ </td></tr>
      @ <tr><th>Other&nbsp;Links:</th>
      @   <td>
      @     %z(href("%R/dir?ci=%S",zUuid))files</a>
      @   | %z(href("%R/artifact/%S",zUuid))manifest</a>
      @   | <a href="%s(g.zTop)/vdiff?from=pbranch:%S(zUuid)&to=%S(zUuid)">
      @           vdiff to parent branch</a>
      if( g.perm.Write ){
        @   | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
      }
      @   </td>
      @ </tr>
    }
    @ </table>
  }else{
    style_header("Check-in Information");
................................................................................
  if( zParent ){
    @ <div class="section">Changes</div>
    @ <div class="sectionmenu">
    showDiff = g.zPath[0]!='c';
    if( db_get_boolean("show-version-diffs", 0)==0 ){
      showDiff = !showDiff;
      if( showDiff ){
        @ %z(xhref("class='button'","%R/vinfo/%T",zName))
        @ hide&nbsp;diffs</a>
        if( sideBySide ){
          @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
          @ unified&nbsp;diffs</a>
        }else{
          @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
          @ side-by-side&nbsp;diffs</a>
        }
      }else{
        @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
        @ show&nbsp;unified&nbsp;diffs</a>
        @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
        @ show&nbsp;side-by-side&nbsp;diffs</a>
      }
    }else{
      if( showDiff ){
        @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a>
        if( sideBySide ){
          @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName))
          @ unified&nbsp;diffs</a>
        }else{
          @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName))
          @ side-by-side&nbsp;diffs</a>
        }
      }else{
        @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName))
        @ show&nbsp;unified&nbsp;diffs</a>
        @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
        @ show&nbsp;side-by-side&nbsp;diffs</a>
      }
    }
    @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
    @ patch</a></div>
    db_prepare(&q,
       "SELECT name,"
       "       mperm,"
       "       (SELECT uuid FROM blob WHERE rid=mlink.pid),"
       "       (SELECT uuid FROM blob WHERE rid=mlink.fid),"
       "       (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
................................................................................
    @ <tr><th>Date:</th><td>
    hyperlink_to_date(zDate, "</td></tr>");
    if( g.perm.Setup ){
      @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
    }
    @ <tr><th>Original&nbsp;User:</th><td>
    hyperlink_to_user(zUser, zDate, "</td></tr>");
    if( g.perm.Hyperlink ){
      @ <tr><th>Commands:</th>
      @   <td>
      @     %z(href("%R/whistory?name=%t",zName))history</a>
      @     | %z(href("%R/artifact/%S",zUuid))raw-text</a>
      @   </td>
      @ </tr>
    }
    @ </table></p>
  }else{
    style_header("Wiki Information");
    rid = 0;
................................................................................
** manifest.  Return the number of errors.
*/
static Manifest *vdiff_parse_manifest(const char *zParam, int *pRid){
  int rid;

  *pRid = rid = name_to_rid_www(zParam);
  if( rid==0 ){
    const char *z = P(zParam);
    if( z==0 || z[0]==0 ){
      webpage_error("Missing \"%s\" query parameter.", zParam);
    }else{
      webpage_error("No such artifact: \"%s\"", z);
    }
    return 0;
  }
  if( !is_a_version(rid) ){
    webpage_error("Artifact %s is not a checkin.", P(zParam));
    return 0;
  }
  return manifest_get(rid, CFTYPE_MANIFEST);
................................................................................
  }
  db_finalize(&q);
}


/*
** WEBPAGE: vdiff
** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN
**
** Show all differences between two checkins.  
*/
void vdiff_page(void){
  int ridFrom, ridTo;
  int showDetail = 0;
  int sideBySide = 0;
  int diffFlags = 0;
  Manifest *pFrom, *pTo;
  ManifestFile *pFileFrom, *pFileTo;
  const char *zBranch;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  login_anonymous_available();

  zBranch = P("branch");
  if( zBranch && zBranch[0] ){
    cgi_replace_parameter("from", mprintf("root:%s", zBranch));
    cgi_replace_parameter("to", zBranch);
  }
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;
  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  sideBySide = atoi(PD("sbs","1"));
  showDetail = atoi(PD("detail","0"));
  if( !showDetail && sideBySide ) showDetail = 1;
  if (showDetail){
    style_submenu_element("Abstract", "abstract",
                          "%s/vdiff?from=%T&to=%T&detail=0&sbs=0",
                          g.zTop, P("from"), P("to"));
................................................................................
      if( mPerm==PERM_LNK ){
        @ <li>Symbolic link
      }else if( mPerm==PERM_EXE ){
        @ <li>Executable file
      }else{
        @ <li>File        
      }
      @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>




      @ <ul>
      prevName = fossil_strdup(zName);
    }
    @ <li>
    hyperlink_to_date(zDate,"");
    @ - part of checkin
    hyperlink_to_uuid(zVers);
    if( zBr && zBr[0] ){
      @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>



    }

    @ - %w(zCom) (user:
    hyperlink_to_user(zUser,zDate,")");

    if( g.perm.Hyperlink ){

      @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName))
      @ [annotate]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
................................................................................
    const char *zDate = db_column_text(&q, 1);
    const char *zUser = db_column_text(&q, 2);
    if( cnt>0 ){
      @ Also wiki page
    }else{
      @ Wiki page
    }
    @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by





    hyperlink_to_user(zUser,zDate," on");
    hyperlink_to_date(zDate,".");
    nWiki++;
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%s.wiki", zPagename);
    }
................................................................................
    /* const char *zSrc = db_column_text(&q, 4); */
    if( cnt>0 ){
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      if( g.perm.Hyperlink && g.perm.RdTkt ){
        @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
      }else{
        @ ticket [%S(zTarget)]
      }
    }else{
      if( g.perm.Hyperlink && g.perm.RdWiki ){
        @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>]
      }else{
        @ wiki page [%h(zTarget)]
      }
    }
    @ added by
    hyperlink_to_user(zUser,zDate," on");
    hyperlink_to_date(zDate,".");
................................................................................
  }
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }
  }else if( linkToView && g.perm.Hyperlink ){
    @ %z(href("%R/artifact/%S",zUuid))[view]</a>
  }
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN
................................................................................
      style_submenu_element("Unified Diff", "udiff",
                            "%s/fdiff?v1=%T&v2=%T&sbs=0",
                            g.zTop, P("v1"), P("v2"));
    }

    if( P("smhdr")!=0 ){
      @ <h2>Differences From Artifact
      @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
      @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2>
    }else{
      @ <h2>Differences From
      @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
      object_description(v1, 0, 0);
      @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>

      object_description(v2, 0, 0);
    }
    @ <hr />
    @ <div class="%s(zStyle)">
    @ %s(blob_str(&diff))
    @ </div>
    blob_reset(&diff);
................................................................................
  rid = name_to_rid_www("name");
  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  style_header("Hex Artifact Content");
................................................................................
    else cgi_append_content("\n", 1);
    z += i;
    if( z[0]=='\n' ) z++;
  }
  if( n<iEnd ) cgi_printf("</div>");
  @ </pre>
  if( iStart ){


    @ <script>gebi('topln').scrollIntoView(true);</script>


  }
}


/*
** WEBPAGE: artifact
** URL: /artifact/ARTIFACTID
................................................................................

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  if( rid==0 ) fossil_redirect_home();
  if( g.perm.Admin ){
    const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  style_header("Artifact Content");
................................................................................
        output_text_with_line_numbers(z, zLn);
      }else{
        @ <pre>
        @ %h(z)
        @ </pre>
      }
    }else if( strncmp(zMime, "image/", 6)==0 ){
      @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img>
    }else{
      @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
    }
    @ </blockquote>
  }
  style_footer();
}  
................................................................................
  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(); return; }
  rid = name_to_rid_www("name");
  if( rid==0 ){ fossil_redirect_home(); }
  zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
  if( g.perm.Admin ){
    if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
      style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
            g.zTop, zUuid);
    }else{
      style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
            g.zTop, zUuid);
    }
  }
  pTktChng = manifest_get(rid, CFTYPE_TICKET);
................................................................................
  if( pTktChng==0 ){
    fossil_redirect_home();
  }
  style_header("Ticket Change Details");
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, 10);
  zTktName[10] = 0;
  if( g.perm.Hyperlink ){
    @ <h2>Changes to ticket
    @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid)))%s(zTktName)</a></h2>
    @
    @ <p>By %h(pTktChng->zUser) on %s(zDate).  See also:
    @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and
    @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p>

  }else{
    @ <h2>Changes to ticket %s(zTktName)</h2>
    @
    @ <p>By %h(pTktChng->zUser) on %s(zDate).
    @ </p>
  }
  @
................................................................................
  };
  int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
  int stdClrFound = 0;
  int i;

  @ <table border="0" cellpadding="0" cellspacing="1">
  if( zIdPropagate ){
    @ <tr><td colspan="6" align="left"><label>
    if( fPropagate ){
      @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" />
    }else{
      @ <input type="checkbox" name="%s(zIdPropagate)" />
    }
    @ Propagate color to descendants</label></td></tr>
  }
  @ <tr>
  for(i=0; i<nColor; i++){
    const char *zClr = aColor[i].zColor;
    if( zClr==0 ) zClr = aColor[i].zCName;
    if( zClr[0] ){
      @ <td style="background-color: %h(zClr);">
................................................................................
  const char *zNewTagFlag;
  const char *zNewTag;
  const char *zNewBrFlag;
  const char *zNewBranch;
  const char *zCloseFlag;
  int fPropagateColor;          /* True if color propagates before edit */
  int fNewPropagateColor;       /* True if color propagates after edit */
  const char *zChngTime = 0;     /* Value of chngtime= query param, if any */
  char *zUuid;
  Blob comment;
  Stmt q;
  
  login_check_credentials();
  if( !g.perm.Write ){ login_needed(); return; }
  rid = name_to_typed_rid(P("r"), "ci");
................................................................................
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
                        "  FROM event WHERE objid=%d", rid);
  if( zComment==0 ) fossil_redirect_home();
  if( P("cancel") ){
    cgi_redirectf("ci?name=%s", zUuid);
  }
  if( g.perm.Setup ) zChngTime = P("chngtime");
  zNewComment = PD("c",zComment);
  zUser = db_text(0, "SELECT coalesce(euser,user)"
                     "  FROM event WHERE objid=%d", rid);
  if( zUser==0 ) fossil_redirect_home();
  zNewUser = PDT("u",zUser);
  zDate = db_text(0, "SELECT datetime(mtime)"
                     "  FROM event WHERE objid=%d", rid);
................................................................................
  if( P("apply") ){
    Blob ctrl;
    char *zNow;
    int nChng = 0;

    login_verify_csrf_secret();
    blob_zero(&ctrl);
    zNow = date_in_standard_format(zChngTime ? zChngTime : "now");
    blob_appendf(&ctrl, "D %s\n", zNow);
    db_multi_exec("CREATE TEMP TABLE newtags(tag UNIQUE, prefix, value)");
    if( zNewColor[0]
     && (fPropagateColor!=fNewPropagateColor 
             || fossil_strcmp(zColor,zNewColor)!=0)
    ){
      char *zPrefix = "+";
................................................................................
      }
      nTag++;
    }
    db_finalize(&q);
    blob_appendf(&suffix, ")");
    @ %s(blob_str(&suffix))
    @ </td></tr></table>
    if( zChngTime ){
      @ <p>The timestamp on the tag used to make the changes above
      @ will be overridden as: %s(date_in_standard_format(zChngTime))</p>
    }
    @ </blockquote>
    @ <hr />
    blob_reset(&suffix);
  }
  @ <p>Make changes to attributes of check-in
  @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
  @ <form action="%s(g.zTop)/ci_edit" method="post"><div>
  login_insert_csrf_secret();
  @ <input type="hidden" name="r" value="%S(zUuid)" />
  @ <table border="0" cellspacing="10">

  @ <tr><td align="right" valign="top"><b>User:</b></td>
  @ <td valign="top">
................................................................................
  @ <textarea name="c" rows="10" cols="80">%h(zNewComment)</textarea>
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Check-in Time:</b></td>
  @ <td valign="top">
  @   <input type="text" name="dt" size="20" value="%h(zNewDate)" />
  @ </td></tr>

  if( zChngTime ){
    @ <tr><td align="right" valign="top"><b>Timestamp of this change:</b></td>
    @ <td valign="top">
    @   <input type="text" name="chngtime" size="20" value="%h(zChngTime)" />
    @ </td></tr>
  }

  @ <tr><td align="right" valign="top"><b>Background Color:</b></td>
  @ <td valign="top">
  render_color_chooser(fNewPropagateColor, zNewColor, "pclr", "clr", "clrcust");
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Tags:</b></td>
  @ <td valign="top">
  @ <label><input type="checkbox" id="newtag" name="newtag"%s(zNewTagFlag) />
  @ Add the following new tag name to this check-in:</label>
  @ <input type="text" style="width:15;" name="tagname" value="%h(zNewTag)"
  @ onkeyup="gebi('newtag').checked=!!this.value" />
  db_prepare(&q,
     "SELECT tag.tagid, tagname FROM tagxref, tag"
     " WHERE tagxref.rid=%d AND tagtype>0 AND tagxref.tagid=tag.tagid"
     " ORDER BY CASE WHEN tagname GLOB 'sym-*' THEN substr(tagname,5)"
     "               ELSE tagname END /*sort*/",
     rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    int tagid = db_column_int(&q, 0);
    const char *zTagName = db_column_text(&q, 1);
    char zLabel[30];
    sqlite3_snprintf(sizeof(zLabel), zLabel, "c%d", tagid);
    @ <br /><label>
    if( P(zLabel) ){
      @ <input type="checkbox" name="c%d(tagid)" checked="checked" />
    }else{
      @ <input type="checkbox" name="c%d(tagid)" />
    }
    if( strncmp(zTagName, "sym-", 4)==0 ){
      @ Cancel tag <b>%h(&zTagName[4])</b></label>
    }else{
      @ Cancel special tag <b>%h(zTagName)</b></label>
    }
  }
  db_finalize(&q);
  @ </td></tr>

  @ <tr><td align="right" valign="top"><b>Branching:</b></td>
  @ <td valign="top">
  @ <label><input id="newbr" type="checkbox" name="newbr"%s(zNewBrFlag) />
  @ Make this check-in the start of a new branch named:</label>
  @ <input type="text" style="width:15;" name="brname" value="%h(zNewBranch)"
  @ onkeyup="gebi('newbr').checked=!!this.value" />
  @ </td></tr>

  if( is_a_leaf(rid)
   && !db_exists("SELECT 1 FROM tagxref "
                 " WHERE tagid=%d AND rid=%d AND tagtype>0",
                 TAG_CLOSED, rid)
  ){
    @ <tr><td align="right" valign="top"><b>Leaf Closure:</b></td>
    @ <td valign="top">
    @ <label><input type="checkbox" name="close"%s(zCloseFlag) />
    @ Mark this leaf as "closed" so that it no longer appears on the
    @ "leaves" page and is no longer labeled as a "<b>Leaf</b>".</label>
    @ </td></tr>
  }


  @ <tr><td colspan="2">
  @ <input type="submit" name="preview" value="Preview" />
  @ <input type="submit" name="apply" value="Apply Changes" />
  @ <input type="submit" name="cancel" value="Cancel" />
  @ </td></tr>
  @ </table>
  @ </div></form>
  style_footer();
}

Changes to src/json.c.

173
174
175
176
177
178
179
180


181
182
183
184
185
186
187
...
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
...
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
...
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
...
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
...
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
....
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
....
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
....
1663
1664
1665
1666
1667
1668
1669

1670
1671
1672
1673
1674
1675
1676
1677
1678
....
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
....
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
....
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
....
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
....
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
....
2314
2315
2316
2317
2318
2319
2320

2321
2322
2323
2324
2325
2326
2327
2328
....
2337
2338
2339
2340
2341
2342
2343

2344
2345
2346
2347
2348
2349
2350
2351
....
2356
2357
2358
2359
2360
2361
2362

2363

2364
2365
2366
2367
2368
2369
2370
....
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389

#else
#define BEGIN_TIMER 
#define END_TIMER 0.0
#define HAS_TIMER 0
#endif




char fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
................................................................................
**
** If it finds a value and that value is-a JSON number or is a string
** which looks like an integer or is-a JSON bool/null then it is
** converted to an int. If none of those apply then dflt is returned.
*/
int json_getenv_int(char const * pKey, int dflt ){
  cson_value const * v = json_getenv(pKey);
  if(!v){
    return dflt;
  }else if( cson_value_is_number(v) ){

    return (int)cson_value_get_integer(v);
  }else if( cson_value_is_string(v) ){

    char const * sv = cson_string_cstr(cson_value_get_string(v));
    assert( (NULL!=sv) && "This is quite unexpected." );
    return sv ? atoi(sv) : dflt;
  }else if( cson_value_is_bool(v) ){


    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){

    return 0;
  }else{
    /* we should arguably treat JSON null as 0. */

    return dflt;
  }
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
................................................................................
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
char json_getenv_bool(char const * pKey, char dflt ){
  cson_value const * v = json_getenv(pKey);
  if(!v){
    return dflt;
  }else if( cson_value_is_number(v) ){

    return cson_value_get_integer(v) ? 1 : 0;
  }else if( cson_value_is_string(v) ){

    char const * sv = cson_string_cstr(cson_value_get_string(v));

    if(!*sv || ('0'==*sv)){
      return 0;
    }else{
      return ((('1'<=*sv) && ('9'>=*sv))
              || ('t'==*sv) || ('T'==*sv)
              || ('y'==*sv) || ('Y'==*sv)
              )
        ? 1 : 0;
    }
  }else if( cson_value_is_bool(v) ){


    return cson_value_get_bool(v) ? 1 : 0;
  }else if( cson_value_is_null(v) ){

    return 0;
  }else{

    return dflt;
  }
}

/*
** Returns the string form of a json_getenv() value, but ONLY If that
** value is-a String. Non-strings are not converted to strings for
** this purpose. Returned memory is owned by g.json or fossil and is
................................................................................
    g.json.authToken = json_getenv(FossilJsonKeys.authToken);
    if(g.json.authToken
       && cson_value_is_string(g.json.authToken)
       && !PD(login_cookie_name(),NULL)){
      /* tell fossil to use this login info.

      FIXME?: because the JSON bits don't carry around
      login_cookie_name(), there is a potential login hijacking
      window here. We may need to change the JSON auth token to be
      in the form: login_cookie_name()=...

      Then again, the hardened cookie value helps ensure that
      only a proper key/value match is valid.
      */
      cgi_replace_parameter( login_cookie_name(), cson_value_get_cstr(g.json.authToken) );
    }else if( g.isHTTP ){
      /* try fossil's conventional cookie. */
................................................................................
** for consistency with how json_err() works.
*/
void json_warn( int code, char const * fmt, ... ){
  cson_object * obj = NULL;
  assert( (code>FSL_JSON_W_START)
          && (code<FSL_JSON_W_END)
          && "Invalid warning code.");
  if(!g.json.warnings.v){
    g.json.warnings.v = cson_value_new_array();
    assert((NULL != g.json.warnings.v) && "Alloc error.");
    g.json.warnings.a = cson_value_get_array(g.json.warnings.v);
    json_gc_add("$WARNINGS",g.json.warnings.v);
  }
  obj = cson_new_object();
  cson_array_append(g.json.warnings.a, cson_object_value(obj));
  cson_object_set(obj,"code",cson_value_new_integer(code));
  if(fmt && *fmt){
    /* FIXME: treat NULL fmt as standard warning message for
       the code, but we don't have those yet.
    */
    va_list vargs;
    char * msg;
................................................................................
    if( !*p || (separator == *p) ){
      if( len ){/* append head..(head+len) as next array
                   element. */
        cson_value * part = NULL;
        char * zPart = NULL;
        ++rc;
        assert( head != p );
        zPart = (char*)malloc(len+1);
        assert( (zPart != NULL) && "malloc failure" );
        memcpy(zPart, head, len);
        zPart[len] = 0;
        if(doDeHttp){
          dehttpize(zPart);
        }
        if( *zPart ){ /* should only fail if someone manages to url-encoded a NUL byte */
          part = cson_value_new_string(zPart, strlen(zPart));
................................................................................
          fossil_exit(1)
            /* Not fossil_panic() b/c this code needs to be able to
              run before some of the fossil/json bits are initialized,
              and fossil_panic() calls into the JSON API.
            */
            ;
        }
        free(zPart);
        len = 0;
      }
      if( !*p ){
        break;
      }
      head = p+1;
      while( *head && fossil_isspace(*head) ){
................................................................................
**
** The returned value is owned by the caller. If not NULL then it
** _will_ have a JSON type of Array.
*/
cson_value * json_string_split2( char const * zStr,
                                 char separator,
                                 char doDeHttp ){
  cson_value * v = cson_value_new_array();
  cson_array * a = cson_value_get_array(v);
  int rc = json_string_split( zStr, separator, doDeHttp, a );
  if( 0 == rc ){
    cson_value_free(v);

    v = NULL;
  }else if(rc<0){
    cson_value_free(v);
    v = NULL;
  }
  return v;

}


/*
** Performs some common initialization of JSON-related state.  Must be
** called by the json_page_top() and json_cmd_top() dispatching
** functions to set up the JSON stat used by the dispatched functions.
................................................................................
  INT(g.json, dispatchDepth);
  VAL(authToken, g.json.authToken);
  CSTR(g.json, jsonp);
  VAL(gc, g.json.gc.v);
  VAL(cmd, g.json.cmd.v);
  VAL(param, g.json.param.v);
  VAL(POST, g.json.post.v);
  VAL(warnings, g.json.warnings.v);
  /*cson_output_opt outOpt;*/

  
#undef INT
#undef CSTR
#undef VAL
  return cson_object_value(pay);
................................................................................
    double span;
    span = END_TIMER;
    /* i'm actually seeing sub-ms runtimes in some tests, but a time of
       0 is "just wrong", so we'll bump that up to 1ms.
    */
    cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)((span>1.0)?span:1)));
  }
  if(g.json.warnings.v){
    tmp = g.json.warnings.v;
    SET("warnings");
  }
  
  /* Only add the payload to SUCCESS responses. Else delete it. */
  if( NULL != payload ){
    if( resultCode ){
      cson_value_free(payload);
................................................................................
  assert( (code>=1000) && (code<=9999) );
  free(g.zErrMsg);
  g.json.resultCode = code;
  if(!fmt || !*fmt){
    g.zErrMsg = mprintf("%s", json_err_cstr(code));
  }else{
    va_list vargs;

    va_start(vargs,fmt);
    char * msg = vmprintf(fmt, vargs);
    va_end(vargs);
    g.zErrMsg = msg;
  }
  return code;
}

/*
................................................................................
    if(!a){
      a = cson_new_array();
      assert(NULL!=a);
    }
    if(!colNames){
      colNamesV = cson_sqlite3_column_names(pStmt->pStmt);
      assert(NULL != colNamesV);
      cson_value_add_reference(colNamesV)/*avoids an ownership problem*/;
      colNames = cson_value_get_array(colNamesV);
      assert(NULL != colNames);
    }      
    row = cson_sqlite3_row_to_object2(pStmt->pStmt, colNames);
    if(!row && !warnMsg){
      warnMsg = "Could not convert at least one result row to JSON.";
      continue;
    }
    if( 0 != cson_array_append(a, row) ){
      cson_value_free(row);
      assert( 0 && "Alloc error.");
      if(pTgt != a) {
        cson_free_array(a);
      }

      return NULL;
    }
  }
  cson_value_free(colNamesV);
  if(warnMsg){
    json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg );
  }
................................................................................
}

/*
** Impl of /json/resultCodes
**
*/
cson_value * json_page_resultCodes(){
    cson_value * listV = cson_value_new_array();
    cson_array * list = cson_value_get_array(listV);
    cson_value * objV = NULL;
    cson_object * obj = NULL;
    cson_string * kRC;
    cson_string * kSymbol;
    cson_string * kNumber;
    cson_string * kDesc;
    cson_array_reserve( list, 35 );
    kRC = cson_new_string("resultCode",10);
    kSymbol = cson_new_string("cSymbol",7);
    kNumber = cson_new_string("number",6);
    kDesc = cson_new_string("description",11);
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
    cson_object_set_s(obj, kRC, json_new_string(json_rc_cstr(FSL_JSON_E_##K)) ); \
    cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) );             \
    cson_object_set_s(obj, kNumber, cson_value_new_integer(FSL_JSON_E_##K) );        \
    cson_object_set_s(obj, kDesc, json_new_string(json_err_cstr(FSL_JSON_E_##K))); \
    cson_array_append( list, objV ); obj = NULL; objV = NULL

    C(GENERIC);
    C(INVALID_REQUEST);
    C(UNKNOWN_COMMAND);
    C(UNKNOWN);
    C(TIMEOUT);
    C(ASSERT);
................................................................................
    C(STMT_BIND);
    C(STMT_EXEC);
    C(DB_LOCKED);
    C(DB_NEEDS_REBUILD);
    C(DB_NOT_FOUND);
    C(DB_NOT_VALID);
#undef C
    return listV;
}


/*
** /json/version implementation.
**
** Returns the payload object (owned by the caller).
................................................................................
  FSET(MANIFEST_DATE,"manifestDate");
  FSET(MANIFEST_YEAR,"manifestYear");
  FSET(RELEASE_VERSION,"releaseVersion");
  cson_object_set( jobj, "releaseVersionNumber",
                   cson_value_new_integer(RELEASE_VERSION_NUMBER) );
  cson_object_set( jobj, "resultCodeParanoiaLevel",
                   cson_value_new_integer(g.json.errorDetailParanoia) );
  /*FSET(FOSSIL_JSON_API_VERSION, "jsonApiVersion" );*/
#undef FSET
  return jval;
}


/*
** Returns the current user's capabilities string as a String value.
................................................................................
  ADD(Setup,"setup");
  ADD(Admin,"admin");
  ADD(Delete,"delete");
  ADD(Password,"password");
  ADD(Query,"query"); /* don't think this one is actually used */
  ADD(Write,"checkin");
  ADD(Read,"checkout");
  ADD(History,"history");
  ADD(Clone,"clone");
  ADD(RdWiki,"readWiki");
  ADD(NewWiki,"createWiki");
  ADD(ApndWiki,"appendWiki");
  ADD(WrWiki,"editWiki");
  ADD(RdTkt,"readTicket");
  ADD(NewTkt,"createTicket");
................................................................................
  }
  payload = json_create_response(rc, NULL, payload);
  json_send_response(payload);
  cson_value_free(payload);
  return rc;
}


#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** WEBPAGE: json
**
** Pages under /json/... must be entered into JsonPageDefs.
** This function dispatches them, and is the HTTP equivalent of
** json_cmd_top().
*/
................................................................................
                                    " Try one of: ");
    return;
  }
  json_dispatch_root_command( zCommand );
}
#endif /* FOSSIL_ENABLE_JSON for mkindex */


#ifdef FOSSIL_ENABLE_JSON /* dupe ifdef needed for mkindex */
/*
** This function dispatches json commands and is the CLI equivalent of
** json_page_top().
**
** COMMAND: json
**
** Usage: %fossil json SUBCOMMAND ?OPTIONS?
................................................................................
**
** The commands include:
**
**   anonymousPassord
**   artifact
**   branch
**   cap

**   diff

**   g
**   login
**   logout
**   query
**   rebuild
**   report
**   resultCodes
................................................................................
**   timeline
**   user
**   version (alias: HAI)
**   whoami
**   wiki
**
** Run '%fossil json' without any subcommand to see the full list (but be
** aware that some listed might not yet be implemented).
**
** PS: the notable TODO-commands include: config, dir, finfo, ticket
**
*/
void json_cmd_top(void){
  char const * cmd = NULL;
  int rc = 0;
  BEGIN_TIMER;
  memset( &g.perm, 0xff, sizeof(g.perm) )







|
>
>







 







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







 







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







 







|
|
|







 







|
|
|
<
|


|







 







|
<







 







|







 







<
|

|
<
>
|
<
<
<

<
>







 







|







 







|
|







 







>

|







 







|










<



>







 







<
|
<










|




|







 







|







 







|







 







|







 







>
|







 







>
|







 







>

>







 







|
<
<







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
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
...
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
...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
...
870
871
872
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887
888
889
890
...
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
992
993
994
995
996
997
998

999
1000
1001

1002
1003



1004

1005
1006
1007
1008
1009
1010
1011
1012
....
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
....
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
....
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
....
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
....
1828
1829
1830
1831
1832
1833
1834

1835

1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
....
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
....
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
....
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
....
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
....
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
....
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
....
2376
2377
2378
2379
2380
2381
2382
2383


2384
2385
2386
2387
2388
2389
2390

#else
#define BEGIN_TIMER 
#define END_TIMER 0.0
#define HAS_TIMER 0
#endif

/*
** Returns true (non-0) if fossil appears to be running in JSON mode.
*/
char fossil_has_json(){
  return g.json.isJsonMode && (g.isHTTP || g.json.post.o);
}

/*
** Placeholder /json/XXX page impl for NYI (Not Yet Implemented)
** (but planned) pages/commands.
................................................................................
**
** If it finds a value and that value is-a JSON number or is a string
** which looks like an integer or is-a JSON bool/null then it is
** converted to an int. If none of those apply then dflt is returned.
*/
int json_getenv_int(char const * pKey, int dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return (int)cson_value_get_integer(v);

    case CSON_TYPE_STRING: {
      char const * sv = cson_string_cstr(cson_value_get_string(v));
      assert( (NULL!=sv) && "This is quite unexpected." );
      return sv ? atoi(sv) : dflt;

    }
    case CSON_TYPE_BOOL:
      return cson_value_get_bool(v) ? 1 : 0;

    case CSON_TYPE_NULL:
      return 0;


    default:
      return dflt;
  }
}


/*
** Wrapper around json_getenv() which tries to evaluate a payload/env
** value as a boolean. Uses mostly the same logic as
................................................................................
** either 0 or 1, as opposed to "0 or non-zero", so that clients can
** pass a different value as dflt. Thus they can use, e.g. -1 to know
** whether or not this function found a match (it will return -1 in
** that case).
*/
char json_getenv_bool(char const * pKey, char dflt ){
  cson_value const * v = json_getenv(pKey);
  const cson_type_id type = v ? cson_value_type_id(v) : CSON_TYPE_UNDEF;
  switch(type){
    case CSON_TYPE_INTEGER:
    case CSON_TYPE_DOUBLE:
      return cson_value_get_integer(v) ? 1 : 0;

    case CSON_TYPE_STRING: {
      char const * sv = cson_string_cstr(cson_value_get_string(v));
      assert( (NULL!=sv) && "This is quite unexpected." );
      if(!*sv || ('0'==*sv)){
        return 0;
      }else{
        return ((('1'<=*sv) && ('9'>=*sv))
                || ('t'==*sv) || ('T'==*sv)
                || ('y'==*sv) || ('Y'==*sv)
                )
          ? 1 : 0;
      }

    }
    case CSON_TYPE_BOOL:
      return cson_value_get_bool(v) ? 1 : 0;

    case CSON_TYPE_NULL:
      return 0;

    default:
      return dflt;
  }
}

/*
** Returns the string form of a json_getenv() value, but ONLY If that
** value is-a String. Non-strings are not converted to strings for
** this purpose. Returned memory is owned by g.json or fossil and is
................................................................................
    g.json.authToken = json_getenv(FossilJsonKeys.authToken);
    if(g.json.authToken
       && cson_value_is_string(g.json.authToken)
       && !PD(login_cookie_name(),NULL)){
      /* tell fossil to use this login info.

      FIXME?: because the JSON bits don't carry around
      login_cookie_name(), there is(?) a potential(?) login hijacking
      window here. We may need to change the JSON auth token to be in
      the form: login_cookie_name()=...

      Then again, the hardened cookie value helps ensure that
      only a proper key/value match is valid.
      */
      cgi_replace_parameter( login_cookie_name(), cson_value_get_cstr(g.json.authToken) );
    }else if( g.isHTTP ){
      /* try fossil's conventional cookie. */
................................................................................
** for consistency with how json_err() works.
*/
void json_warn( int code, char const * fmt, ... ){
  cson_object * obj = NULL;
  assert( (code>FSL_JSON_W_START)
          && (code<FSL_JSON_W_END)
          && "Invalid warning code.");
  if(!g.json.warnings){
    g.json.warnings = cson_new_array();
    assert((NULL != g.json.warnings) && "Alloc error.");

    json_gc_add("$WARNINGS",cson_array_value(g.json.warnings));
  }
  obj = cson_new_object();
  cson_array_append(g.json.warnings, cson_object_value(obj));
  cson_object_set(obj,"code",cson_value_new_integer(code));
  if(fmt && *fmt){
    /* FIXME: treat NULL fmt as standard warning message for
       the code, but we don't have those yet.
    */
    va_list vargs;
    char * msg;
................................................................................
    if( !*p || (separator == *p) ){
      if( len ){/* append head..(head+len) as next array
                   element. */
        cson_value * part = NULL;
        char * zPart = NULL;
        ++rc;
        assert( head != p );
        zPart = (char*)fossil_malloc(len+1);

        memcpy(zPart, head, len);
        zPart[len] = 0;
        if(doDeHttp){
          dehttpize(zPart);
        }
        if( *zPart ){ /* should only fail if someone manages to url-encoded a NUL byte */
          part = cson_value_new_string(zPart, strlen(zPart));
................................................................................
          fossil_exit(1)
            /* Not fossil_panic() b/c this code needs to be able to
              run before some of the fossil/json bits are initialized,
              and fossil_panic() calls into the JSON API.
            */
            ;
        }
        fossil_free(zPart);
        len = 0;
      }
      if( !*p ){
        break;
      }
      head = p+1;
      while( *head && fossil_isspace(*head) ){
................................................................................
**
** The returned value is owned by the caller. If not NULL then it
** _will_ have a JSON type of Array.
*/
cson_value * json_string_split2( char const * zStr,
                                 char separator,
                                 char doDeHttp ){

  cson_array * a = cson_new_array();
  int rc = json_string_split( zStr, separator, doDeHttp, a );
  if( 0>=rc ){

    cson_free_array(a);
    a = NULL;



  }

  return a ? cson_array_value(a) : NULL;
}


/*
** Performs some common initialization of JSON-related state.  Must be
** called by the json_page_top() and json_cmd_top() dispatching
** functions to set up the JSON stat used by the dispatched functions.
................................................................................
  INT(g.json, dispatchDepth);
  VAL(authToken, g.json.authToken);
  CSTR(g.json, jsonp);
  VAL(gc, g.json.gc.v);
  VAL(cmd, g.json.cmd.v);
  VAL(param, g.json.param.v);
  VAL(POST, g.json.post.v);
  VAL(warnings, cson_array_value(g.json.warnings));
  /*cson_output_opt outOpt;*/

  
#undef INT
#undef CSTR
#undef VAL
  return cson_object_value(pay);
................................................................................
    double span;
    span = END_TIMER;
    /* i'm actually seeing sub-ms runtimes in some tests, but a time of
       0 is "just wrong", so we'll bump that up to 1ms.
    */
    cson_object_set(o,"procTimeMs", cson_value_new_integer((cson_int_t)((span>1.0)?span:1)));
  }
  if(g.json.warnings){
    tmp = cson_array_value(g.json.warnings);
    SET("warnings");
  }
  
  /* Only add the payload to SUCCESS responses. Else delete it. */
  if( NULL != payload ){
    if( resultCode ){
      cson_value_free(payload);
................................................................................
  assert( (code>=1000) && (code<=9999) );
  free(g.zErrMsg);
  g.json.resultCode = code;
  if(!fmt || !*fmt){
    g.zErrMsg = mprintf("%s", json_err_cstr(code));
  }else{
    va_list vargs;
    char * msg;
    va_start(vargs,fmt);
    msg = vmprintf(fmt, vargs);
    va_end(vargs);
    g.zErrMsg = msg;
  }
  return code;
}

/*
................................................................................
    if(!a){
      a = cson_new_array();
      assert(NULL!=a);
    }
    if(!colNames){
      colNamesV = cson_sqlite3_column_names(pStmt->pStmt);
      assert(NULL != colNamesV);
      /*Why? cson_value_add_reference(colNamesV) avoids an ownership problem*/;
      colNames = cson_value_get_array(colNamesV);
      assert(NULL != colNames);
    }      
    row = cson_sqlite3_row_to_object2(pStmt->pStmt, colNames);
    if(!row && !warnMsg){
      warnMsg = "Could not convert at least one result row to JSON.";
      continue;
    }
    if( 0 != cson_array_append(a, row) ){
      cson_value_free(row);

      if(pTgt != a) {
        cson_free_array(a);
      }
      assert( 0 && "Alloc error.");
      return NULL;
    }
  }
  cson_value_free(colNamesV);
  if(warnMsg){
    json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg );
  }
................................................................................
}

/*
** Impl of /json/resultCodes
**
*/
cson_value * json_page_resultCodes(){

    cson_array * list = cson_new_array();

    cson_object * obj = NULL;
    cson_string * kRC;
    cson_string * kSymbol;
    cson_string * kNumber;
    cson_string * kDesc;
    cson_array_reserve( list, 35 );
    kRC = cson_new_string("resultCode",10);
    kSymbol = cson_new_string("cSymbol",7);
    kNumber = cson_new_string("number",6);
    kDesc = cson_new_string("description",11);
#define C(K) obj = cson_new_object(); \
    cson_object_set_s(obj, kRC, json_new_string(json_rc_cstr(FSL_JSON_E_##K)) ); \
    cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) );             \
    cson_object_set_s(obj, kNumber, cson_value_new_integer(FSL_JSON_E_##K) );        \
    cson_object_set_s(obj, kDesc, json_new_string(json_err_cstr(FSL_JSON_E_##K))); \
    cson_array_append( list, cson_object_value(obj) ); obj = NULL;

    C(GENERIC);
    C(INVALID_REQUEST);
    C(UNKNOWN_COMMAND);
    C(UNKNOWN);
    C(TIMEOUT);
    C(ASSERT);
................................................................................
    C(STMT_BIND);
    C(STMT_EXEC);
    C(DB_LOCKED);
    C(DB_NEEDS_REBUILD);
    C(DB_NOT_FOUND);
    C(DB_NOT_VALID);
#undef C
    return cson_array_value(list);
}


/*
** /json/version implementation.
**
** Returns the payload object (owned by the caller).
................................................................................
  FSET(MANIFEST_DATE,"manifestDate");
  FSET(MANIFEST_YEAR,"manifestYear");
  FSET(RELEASE_VERSION,"releaseVersion");
  cson_object_set( jobj, "releaseVersionNumber",
                   cson_value_new_integer(RELEASE_VERSION_NUMBER) );
  cson_object_set( jobj, "resultCodeParanoiaLevel",
                   cson_value_new_integer(g.json.errorDetailParanoia) );
  FSET(FOSSIL_JSON_API_VERSION, "jsonApiVersion" );
#undef FSET
  return jval;
}


/*
** Returns the current user's capabilities string as a String value.
................................................................................
  ADD(Setup,"setup");
  ADD(Admin,"admin");
  ADD(Delete,"delete");
  ADD(Password,"password");
  ADD(Query,"query"); /* don't think this one is actually used */
  ADD(Write,"checkin");
  ADD(Read,"checkout");
  ADD(Hyperlink,"history");
  ADD(Clone,"clone");
  ADD(RdWiki,"readWiki");
  ADD(NewWiki,"createWiki");
  ADD(ApndWiki,"appendWiki");
  ADD(WrWiki,"editWiki");
  ADD(RdTkt,"readTicket");
  ADD(NewTkt,"createTicket");
................................................................................
  }
  payload = json_create_response(rc, NULL, payload);
  json_send_response(payload);
  cson_value_free(payload);
  return rc;
}

#ifdef FOSSIL_ENABLE_JSON
/* dupe ifdef needed for mkindex */
/*
** WEBPAGE: json
**
** Pages under /json/... must be entered into JsonPageDefs.
** This function dispatches them, and is the HTTP equivalent of
** json_cmd_top().
*/
................................................................................
                                    " Try one of: ");
    return;
  }
  json_dispatch_root_command( zCommand );
}
#endif /* FOSSIL_ENABLE_JSON for mkindex */

#ifdef FOSSIL_ENABLE_JSON
/* dupe ifdef needed for mkindex */
/*
** This function dispatches json commands and is the CLI equivalent of
** json_page_top().
**
** COMMAND: json
**
** Usage: %fossil json SUBCOMMAND ?OPTIONS?
................................................................................
**
** The commands include:
**
**   anonymousPassord
**   artifact
**   branch
**   cap
**   config
**   diff
**   dir
**   g
**   login
**   logout
**   query
**   rebuild
**   report
**   resultCodes
................................................................................
**   timeline
**   user
**   version (alias: HAI)
**   whoami
**   wiki
**
** Run '%fossil json' without any subcommand to see the full list (but be
** aware that some listed might not yet be fully implemented).


**
*/
void json_cmd_top(void){
  char const * cmd = NULL;
  int rc = 0;
  BEGIN_TIMER;
  memset( &g.perm, 0xff, sizeof(g.perm) )

Changes to src/json_artifact.c.

27
28
29
30
31
32
33




34
35
36
37
38
39
40
41
42
...
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
...
203
204
205
206
207
208
209
210
211
212
213
214
215






216
217
218
219
220
221
222
...
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
...
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
...
324
325
326
327
328
329
330

331
332
333
334
335
336
337
...
369
370
371
372
373
374
375

376
377
378
379
380
381
382
...
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
** Internal callback for /json/artifact handlers. rid refers to
** the rid of a given type of artifact, and each callback is
** specialized to return a JSON form of one type of artifact.
**
** Implementations may assert() that rid refers to requested artifact
** type, since mismatches in the artifact types come from
** json_page_artifact() as opposed to client data.




*/
typedef cson_value * (*artifact_f)( int rid );

/*
** Internal per-artifact-type dispatching helper.
*/
typedef struct ArtifactDispatchEntry {
  /**
     Artifact type name, e.g. "checkin", "ticket", "wiki".
................................................................................

    tmpV = json_tags_for_checkin_rid(rid,0);
    if(tmpV){
      SET("tags",tmpV);
    }

    if( showFiles ){
      tmpV = json_get_changed_files(rid);
      if(tmpV){
        SET("files",tmpV);
      }
    }

#undef SET
  }
................................................................................
  db_finalize(&q);
  return v;
}

/*
** Very incomplete/incorrect impl of /json/artifact/TICKET_ID.
*/
cson_value * json_artifact_ticket( int rid ){
  cson_object * pay = NULL;
  Manifest *pTktChng = NULL;
  static cson_value * eventTypeLabel = NULL;
  if(! g.perm.RdTkt ){
    g.json.resultCode = FSL_JSON_E_DENIED;
    return NULL;
  }
................................................................................
  manifest_destroy(pTktChng);
  return cson_object_value(pay);
}

/*
** Sub-impl of /json/artifact for checkins.
*/
static cson_value * json_artifact_ci( int rid ){
  if(!g.perm.Read){
    json_set_err( FSL_JSON_E_DENIED, "Viewing checkins requires 'o' privileges." );
    return NULL;
  }else{
    return json_artifact_for_ci(rid, 1);






  }
}

/*
** Internal mapping of /json/artifact/FOO commands/callbacks.
*/
static ArtifactDispatchEntry ArtifactDispatchList[] = {
................................................................................
{"ticket", json_artifact_ticket},
{"wiki", json_artifact_wiki},
/* Final entry MUST have a NULL name. */
{NULL,NULL}
};

/*
** Internal helper which returns true (non-0) if the includeContent




** (HTTP) or -content|-c flags (CLI) are set. 
*/ 
static char json_artifact_include_content_flag(){



  return json_find_option_bool("includeContent","content","c",0);
}





cson_value * json_artifact_wiki(int rid){
  if( ! g.perm.RdWiki ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' privileges.");
    return NULL;
  }else{
    char contentFormat = json_wiki_get_content_format_flag(-9);
    if(-9 == contentFormat){
      contentFormat = json_artifact_include_content_flag() ? -1 : 0;
    }
    return json_get_wiki_page_by_rid(rid, contentFormat);
  }
}

/*
** Internal helper for routines which add a "status" flag to file
** artifact data. isNew and isDel should be the "is this object new?" 
................................................................................
  return isNew
    ? "added"
    : (isDel
       ? "removed"
       : "modified");
}

cson_value * json_artifact_file(int rid){
  cson_object * pay = NULL;
  Stmt q = empty_Stmt;
  cson_array * checkin_arr = NULL;



  if( ! g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' privileges.");
    return NULL;
  }
  
  pay = cson_new_object();

  if( json_artifact_include_content_flag() ){

    Blob content = empty_blob;
    const char *zMime;

    content_get(rid, &content);
    zMime = mimetype_from_content(&content);
    cson_object_set(pay, "contentType",
                    json_new_string(zMime ? zMime : "text/plain"));
    cson_object_set(pay, "size", json_new_int( blob_size(&content)) );
    if(!zMime){










      cson_object_set(pay, "content",
                      cson_value_new_string(blob_str(&content),
                                            (unsigned int)blob_size(&content)));
    }




    blob_reset(&content);
  }


















  db_prepare(&q,
      "SELECT filename.name AS name, "
      "  (mlink.pid==0) AS isNew,"
      "  (mlink.fid==0) AS isDel,"
      "  cast(strftime('%%s',event.mtime) as int) AS timestamp,"
      "  coalesce(event.ecomment,event.comment) as comment,"
      "  coalesce(event.euser,event.user) as user,"

      "  a.size AS size,"

      "  b.uuid as uuid, "
#if 0
      "  mlink.mperm as mperm,"
#endif
      "  coalesce((SELECT value FROM tagxref"
                      "  WHERE tagid=%d AND tagtype>0 AND "
                      " rid=mlink.mid),'trunk') as branch"
      "  FROM mlink, filename, event, blob a, blob b"
................................................................................
  /* TODO: add a "state" flag for the file in each checkin,
     e.g. "modified", "new", "deleted".
   */
  checkin_arr = cson_new_array(); 
  cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
  while( (SQLITE_ROW==db_step(&q) ) ){
    cson_object * row = cson_value_get_object(cson_sqlite3_row_to_object(q.pStmt));

    char const isNew = cson_value_get_bool(cson_object_get(row,"isNew"));
    char const isDel = cson_value_get_bool(cson_object_get(row,"isDel"));
    cson_object_set(row, "isNew", NULL);
    cson_object_set(row, "isDel", NULL);
    cson_object_set(row, "state",
                    json_new_string(json_artifact_status_to_string(isNew, isDel)));
    cson_array_append( checkin_arr, cson_object_value(row) );
................................................................................
    if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
      zType = "tag";
      goto handle_entry;
    }
  }
  blob_set(&uuid,zName);
  rc = name_to_uuid(&uuid,-1,"*");

  if(1==rc){
    g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
    goto error;
  }else if(2==rc){
    g.json.resultCode = FSL_JSON_E_AMBIGUOUS_UUID;
    goto error;
  }
................................................................................
  }

  error:
  assert( 0 != g.json.resultCode );
  goto veryend;

  handle_entry:

  assert( (NULL != zType) && "Internal dispatching error." );
  for( ; dispatcher->name; ++dispatcher ){
    if(0!=strcmp(dispatcher->name, zType)){
      continue;
    }else{
      entry = (*dispatcher->func)(rid);
      break;
    }
  }
  if(!g.json.resultCode){
    assert( NULL != entry );
    assert( NULL != zType );
    pay = cson_new_object();
    cson_object_set( pay, "type", json_new_string(zType) );
    /*cson_object_set( pay, "uuid", json_new_string(zUuid) );*/
    cson_object_set( pay, "name", json_new_string(zName ? zName : zUuid) );
    /*cson_object_set( pay, "rid", cson_value_new_integer(rid) );*/
    if(entry){

      cson_object_set(pay, "artifact", entry);
    }
  }
  veryend:
  blob_reset(&uuid);




  return cson_object_value(pay);
}

#endif /* FOSSIL_ENABLE_JSON */







>
>
>
>

|







 







|







 







|







 







|




|
>
>
>
>
>
>







 







|
>
>
>
>
|

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





|
<
|
<







 







|



|
>
>






|

|
>


>


|

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


<
>
>
>
>


>
>
>

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







>
|
>
|







 







>







 







>







 







>





|






<

|
|

<
>





>
>
>
>




27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
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
...
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
...
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
...
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
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
...
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
** Internal callback for /json/artifact handlers. rid refers to
** the rid of a given type of artifact, and each callback is
** specialized to return a JSON form of one type of artifact.
**
** Implementations may assert() that rid refers to requested artifact
** type, since mismatches in the artifact types come from
** json_page_artifact() as opposed to client data.
**
** The pParent parameter points to the response payload object.  It
** _may_ be used to populate "top-level" information in the response
** payload, but normally this is neither necessary nor desired.
*/
typedef cson_value * (*artifact_f)( cson_object * pParent, int rid );

/*
** Internal per-artifact-type dispatching helper.
*/
typedef struct ArtifactDispatchEntry {
  /**
     Artifact type name, e.g. "checkin", "ticket", "wiki".
................................................................................

    tmpV = json_tags_for_checkin_rid(rid,0);
    if(tmpV){
      SET("tags",tmpV);
    }

    if( showFiles ){
      tmpV = json_get_changed_files(rid, 1);
      if(tmpV){
        SET("files",tmpV);
      }
    }

#undef SET
  }
................................................................................
  db_finalize(&q);
  return v;
}

/*
** Very incomplete/incorrect impl of /json/artifact/TICKET_ID.
*/
cson_value * json_artifact_ticket( cson_object * zParent, int rid ){
  cson_object * pay = NULL;
  Manifest *pTktChng = NULL;
  static cson_value * eventTypeLabel = NULL;
  if(! g.perm.RdTkt ){
    g.json.resultCode = FSL_JSON_E_DENIED;
    return NULL;
  }
................................................................................
  manifest_destroy(pTktChng);
  return cson_object_value(pay);
}

/*
** Sub-impl of /json/artifact for checkins.
*/
static cson_value * json_artifact_ci( cson_object * zParent, int rid ){
  if(!g.perm.Read){
    json_set_err( FSL_JSON_E_DENIED, "Viewing checkins requires 'o' privileges." );
    return NULL;
  }else{
    cson_value * artV = json_artifact_for_ci(rid, 1);
    cson_object * art = cson_value_get_object(artV);
    if(art){
      cson_object_merge( zParent, art, CSON_MERGE_REPLACE );
      cson_free_object(art);
    }
    return cson_object_value(zParent);
  }
}

/*
** Internal mapping of /json/artifact/FOO commands/callbacks.
*/
static ArtifactDispatchEntry ArtifactDispatchList[] = {
................................................................................
{"ticket", json_artifact_ticket},
{"wiki", json_artifact_wiki},
/* Final entry MUST have a NULL name. */
{NULL,NULL}
};

/*
** Internal helper which returns:
**
** If the "format" (CLI: -f) flag is set function returns the same as
** json_wiki_get_content_format_flag(), else it returns true (non-0)
** if either the includeContent (HTTP) or -content|-c boolean flags
** (CLI) are set.
*/ 
static char json_artifact_get_content_format_flag(){
  enum { MagicValue = -9 };
  char contentFormat = json_wiki_get_content_format_flag(MagicValue);
  if(MagicValue == contentFormat){
    contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0;
  }
  return contentFormat;
}

extern char json_wiki_get_content_format_flag( char defaultValue ) /* json_wiki.c */;

cson_value * json_artifact_wiki(cson_object * zParent, int rid){
  if( ! g.perm.RdWiki ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'j' privileges.");
    return NULL;
  }else{
    enum { MagicValue = -9 };

    char const contentFormat = json_artifact_get_content_format_flag();

    return json_get_wiki_page_by_rid(rid, contentFormat);
  }
}

/*
** Internal helper for routines which add a "status" flag to file
** artifact data. isNew and isDel should be the "is this object new?" 
................................................................................
  return isNew
    ? "added"
    : (isDel
       ? "removed"
       : "modified");
}

cson_value * json_artifact_file(cson_object * zParent, int rid){
  cson_object * pay = NULL;
  Stmt q = empty_Stmt;
  cson_array * checkin_arr = NULL;
  char contentFormat;
  i64 contentSize = -1;
  char * parentUuid;
  if( ! g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' privileges.");
    return NULL;
  }
  
  pay = zParent;

  contentFormat = json_artifact_get_content_format_flag();
  if( 0 != contentFormat ){
    Blob content = empty_blob;
    const char *zMime;
    char const * zFormat = (contentFormat<1) ? "raw" : "html";
    content_get(rid, &content);
    zMime = mimetype_from_content(&content);
    cson_object_set(zParent, "contentType",
                    json_new_string(zMime ? zMime : "text/plain"));

    if(!zMime){/* text/plain */
      if(0 < blob_size(&content)){
        if( 0 < contentFormat ){/*HTML-size it*/
          Blob html = empty_blob;
          wiki_convert(&content, &html, 0);
          assert( blob_size(&content) < blob_size(&html) );
          blob_swap( &html, &content );
          assert( blob_size(&content) > blob_size(&html) );
          blob_reset( &html );
        }/*else as-is*/
      }
      cson_object_set(zParent, "content",
                      cson_value_new_string(blob_str(&content),
                                            (unsigned int)blob_size(&content)));

    }/*else binary: ignore*/
    contentSize = blob_size(&content);
    cson_object_set(zParent, "contentSize", json_new_int(contentSize) );
    cson_object_set(zParent, "contentFormat", json_new_string(zFormat) );
    blob_reset(&content);
  }
  contentSize = db_int64(-1, "SELECT size FROM blob WHERE rid=%d", rid);
  assert( -1 < contentSize );
  cson_object_set(zParent, "size", json_new_int(contentSize) );

  parentUuid = db_text(NULL,
                       "SELECT DISTINCT p.uuid "
                       "FROM blob p, blob f, mlink m "
                       "WHERE m.pid=p.rid "
                       "AND m.fid=f.rid "
                       "AND f.rid=%d",
                       rid
                       );
  if(parentUuid){
    cson_object_set( zParent, "parent", json_new_string(parentUuid) );
    fossil_free(parentUuid);
  }
  
  /* Find checkins associated with this file... */
  db_prepare(&q,
      "SELECT filename.name AS name, "
      "  (mlink.pid==0) AS isNew,"
      "  (mlink.fid==0) AS isDel,"
      "  cast(strftime('%%s',event.mtime) as int) AS timestamp,"
      "  coalesce(event.ecomment,event.comment) as comment,"
      "  coalesce(event.euser,event.user) as user,"
#if 0
      "  a.size AS size," /* same for all checkins. */
#endif
      "  b.uuid as checkin, "
#if 0
      "  mlink.mperm as mperm,"
#endif
      "  coalesce((SELECT value FROM tagxref"
                      "  WHERE tagid=%d AND tagtype>0 AND "
                      " rid=mlink.mid),'trunk') as branch"
      "  FROM mlink, filename, event, blob a, blob b"
................................................................................
  /* TODO: add a "state" flag for the file in each checkin,
     e.g. "modified", "new", "deleted".
   */
  checkin_arr = cson_new_array(); 
  cson_object_set(pay, "checkins", cson_array_value(checkin_arr));
  while( (SQLITE_ROW==db_step(&q) ) ){
    cson_object * row = cson_value_get_object(cson_sqlite3_row_to_object(q.pStmt));
    /* FIXME: move this isNew/isDel stuff into an SQL CASE statement. */
    char const isNew = cson_value_get_bool(cson_object_get(row,"isNew"));
    char const isDel = cson_value_get_bool(cson_object_get(row,"isDel"));
    cson_object_set(row, "isNew", NULL);
    cson_object_set(row, "isDel", NULL);
    cson_object_set(row, "state",
                    json_new_string(json_artifact_status_to_string(isNew, isDel)));
    cson_array_append( checkin_arr, cson_object_value(row) );
................................................................................
    if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
      zType = "tag";
      goto handle_entry;
    }
  }
  blob_set(&uuid,zName);
  rc = name_to_uuid(&uuid,-1,"*");
  /* FIXME: check for a filename if all else fails. */
  if(1==rc){
    g.json.resultCode = FSL_JSON_E_RESOURCE_NOT_FOUND;
    goto error;
  }else if(2==rc){
    g.json.resultCode = FSL_JSON_E_AMBIGUOUS_UUID;
    goto error;
  }
................................................................................
  }

  error:
  assert( 0 != g.json.resultCode );
  goto veryend;

  handle_entry:
  pay = cson_new_object();
  assert( (NULL != zType) && "Internal dispatching error." );
  for( ; dispatcher->name; ++dispatcher ){
    if(0!=strcmp(dispatcher->name, zType)){
      continue;
    }else{
      entry = (*dispatcher->func)(pay, rid);
      break;
    }
  }
  if(!g.json.resultCode){
    assert( NULL != entry );
    assert( NULL != zType );

    cson_object_set( pay, "type", json_new_string(zType) );
    cson_object_set( pay, "uuid", json_new_string(zUuid) );
    /*cson_object_set( pay, "name", json_new_string(zName ? zName : zUuid) );*/
    /*cson_object_set( pay, "rid", cson_value_new_integer(rid) );*/

    if(cson_value_is_object(entry) && (cson_value_get_object(entry) != pay)){
      cson_object_set(pay, "artifact", entry);
    }
  }
  veryend:
  blob_reset(&uuid);
  if(g.json.resultCode && pay){
    cson_free_object(pay);
    pay = NULL;
  }
  return cson_object_value(pay);
}

#endif /* FOSSIL_ENABLE_JSON */

Changes to src/json_detail.h.

18
19
20
21
22
23
24
25
26
27





28
29
30
31
32
33
34
35
36
...
170
171
172
173
174
175
176



177
178
179
180
181
182
183
...
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
...
262
263
264
265
266
267
268



269
270
271
**
*/

#include "cson_amalgamation.h"

/**
   FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest
   "significant" change to the JSON API (a change in an interface
   or new functionality). It is sent as part of the /json/version
   request. We could arguably add it to each response.





*/
#define FOSSIL_JSON_API_VERSION "20120409"

/*
** Impl details for the JSON API which need to be shared
** across multiple C files.
*/

/*
................................................................................
  ** Which mode(s) of execution does func() support:
  **
  ** <0 = CLI only, >0 = HTTP only, 0==both
  **
  ** Now that we can simulate POST in CLI mode, the distinction
  ** between them has disappeared in most (or all) cases, so 0 is the
  ** the standard value.



  */
  char runMode;
} JsonPageDef;

/*
** Holds common keys used for various JSON API properties.
*/
................................................................................
** values and NULL is returned. If non-NULL is returned, ownership is
** transfered to the caller (but the g.json error state might still be
** set in that case, so the caller must check that or pass it on up
** the dispatch chain).
*/
cson_value * json_page_dispatch_helper(JsonPageDef const * pages);

/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki();

/*
** Implements /json/timeline/wiki and /json/wiki/timeline.
*/
cson_value * json_timeline_wiki();

/*
** Implements /json/timeline family of functions.
*/
cson_value * json_page_timeline();

/*
** Convenience wrapper around cson_value_new_string().
** Returns NULL if str is NULL or on allocation error.
*/
cson_value * json_new_string( char const * str );

/*
................................................................................
**
** Whether or not we need to take args from CLI or POST data makes a
** difference in argument/parameter handling in many JSON rountines,
** and thus this distinction.
*/
char fossil_has_json();





#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
#endif /* FOSSIL_ENABLE_JSON */







|
|
|
>
>
>
>
>

|







 







>
>
>







 







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







 







>
>
>



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
...
218
219
220
221
222
223
224
















225
226
227
228
229
230
231
...
254
255
256
257
258
259
260
261
262
263
264
265
266
**
*/

#include "cson_amalgamation.h"

/**
   FOSSIL_JSON_API_VERSION holds the date (YYYYMMDD) of the latest
   "significant" change to the JSON API (a change in an interface or
   new functionality). It is sent as part of the /json/version
   request. We could arguably add it to each response or even add a
   version number to each response type, allowing very fine (too
   fine?) granularity in compatibility change notification. The
   version number could be included in part of the command dispatching
   framework, allowing the top-level dispatching code to deal with it
   (for the most part).
*/
#define FOSSIL_JSON_API_VERSION "20120713"

/*
** Impl details for the JSON API which need to be shared
** across multiple C files.
*/

/*
................................................................................
  ** Which mode(s) of execution does func() support:
  **
  ** <0 = CLI only, >0 = HTTP only, 0==both
  **
  ** Now that we can simulate POST in CLI mode, the distinction
  ** between them has disappeared in most (or all) cases, so 0 is the
  ** the standard value.
  **
  ** 201207: this is not needed any more. We can get rid of it. Or
  ** keep it around in case it becomes useful again at some point.
  */
  char runMode;
} JsonPageDef;

/*
** Holds common keys used for various JSON API properties.
*/
................................................................................
** values and NULL is returned. If non-NULL is returned, ownership is
** transfered to the caller (but the g.json error state might still be
** set in that case, so the caller must check that or pass it on up
** the dispatch chain).
*/
cson_value * json_page_dispatch_helper(JsonPageDef const * pages);

















/*
** Convenience wrapper around cson_value_new_string().
** Returns NULL if str is NULL or on allocation error.
*/
cson_value * json_new_string( char const * str );

/*
................................................................................
**
** Whether or not we need to take args from CLI or POST data makes a
** difference in argument/parameter handling in many JSON rountines,
** and thus this distinction.
*/
char fossil_has_json();

enum json_get_changed_files_flags {
    json_get_changed_files_ELIDE_PARENT = 1 << 0
};

#endif/*FOSSIL_JSON_DETAIL_H_INCLUDED*/
#endif /* FOSSIL_ENABLE_JSON */

Changes to src/json_dir.c.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  char const * zDX = NULL;
  int nD;
  char * zUuid = NULL;
  char const * zCI = NULL;
  Manifest * pM = NULL;
  Stmt q = empty_Stmt;
  int rid = 0;
  if( !g.perm.History ){
    json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions.");
    return NULL;
  }
  zCI = json_find_option_cstr("checkin",NULL,"ci" );

  /* If a specific check-in is requested, fetch and parse it.  If the
  ** specific check-in does not exist, clear zCI.  zCI==0 will cause all
  ** files from all check-ins to be displayed.







|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  char const * zDX = NULL;
  int nD;
  char * zUuid = NULL;
  char const * zCI = NULL;
  Manifest * pM = NULL;
  Stmt q = empty_Stmt;
  int rid = 0;
  if( !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Requires 'o' permissions.");
    return NULL;
  }
  zCI = json_find_option_cstr("checkin",NULL,"ci" );

  /* If a specific check-in is requested, fetch and parse it.  If the
  ** specific check-in does not exist, clear zCI.  zCI==0 will cause all
  ** files from all check-ins to be displayed.

Changes to src/json_query.c.

63
64
65
66
67
68
69







70
71
72
73
74
75
76
                 "'sql' (-s) argument is missing.");
    return NULL;
  }

  zFmt = json_find_option_cstr2("format",NULL,"f",3);
  if(!zFmt) zFmt = "o";
  db_prepare(&q,"%s", zSql);







  switch(*zFmt){
    case 'a':
      check = cson_sqlite3_stmt_to_json(q.pStmt, &payV, 0);
      break;
    case 'o':
    default:
      check = cson_sqlite3_stmt_to_json(q.pStmt, &payV, 1);







>
>
>
>
>
>
>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
                 "'sql' (-s) argument is missing.");
    return NULL;
  }

  zFmt = json_find_option_cstr2("format",NULL,"f",3);
  if(!zFmt) zFmt = "o";
  db_prepare(&q,"%s", zSql);
  if( 0 == sqlite3_column_count( q.pStmt ) ){
      json_set_err(FSL_JSON_E_USAGE,
                   "Input query has no result columns. "
                   "Only SELECT-like queries are supported.");
      db_finalize(&q);
      return NULL;
  }
  switch(*zFmt){
    case 'a':
      check = cson_sqlite3_stmt_to_json(q.pStmt, &payV, 0);
      break;
    case 'o':
    default:
      check = cson_sqlite3_stmt_to_json(q.pStmt, &payV, 1);

Changes to src/json_report.c.

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
76
77
78
79
80
81
82

83
84
85
86
87
88
89
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
*/
cson_value * json_page_report(){
  if(!g.perm.RdTkt && !g.perm.NewTkt ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'r' or 'n' permissions.");
    return NULL;
  }
  return json_page_dispatch_helper(&JsonPageDefs_Report[0]);
}

/*
** Searches the environment for a "report" parameter
** (CLI: -report/-r #).
**
** If one is not found and argPos is >0 then json_command_arg()
................................................................................
      nReport = atoi(arg);
    }
  }
  return nReport;
}

static cson_value * json_report_create(){

  return NULL;
}

static cson_value * json_report_get(){
  int nReport;
  Stmt q = empty_Stmt;
  cson_value * pay = NULL;
................................................................................

  goto end;

  error:
  assert(0 != g.json.resultCode);
  cson_value_free( cson_object_value(pay) );
  pay = NULL;
    end:

  return pay ? cson_object_value(pay) : NULL;

}

static cson_value * json_report_save(){
  return NULL;
}
#endif /* FOSSIL_ENABLE_JSON */







|







 







>







 







|









49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
*/
cson_value * json_page_report(){
  if(!g.perm.RdTkt && !g.perm.NewTkt ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'r' or 'n' permissions.");
    return NULL;
  }
  return json_page_dispatch_helper(JsonPageDefs_Report);
}

/*
** Searches the environment for a "report" parameter
** (CLI: -report/-r #).
**
** If one is not found and argPos is >0 then json_command_arg()
................................................................................
      nReport = atoi(arg);
    }
  }
  return nReport;
}

static cson_value * json_report_create(){
  json_set_err(FSL_JSON_E_NYI, NULL);
  return NULL;
}

static cson_value * json_report_get(){
  int nReport;
  Stmt q = empty_Stmt;
  cson_value * pay = NULL;
................................................................................

  goto end;

  error:
  assert(0 != g.json.resultCode);
  cson_value_free( cson_object_value(pay) );
  pay = NULL;
  end:

  return pay ? cson_object_value(pay) : NULL;

}

static cson_value * json_report_save(){
  return NULL;
}
#endif /* FOSSIL_ENABLE_JSON */

Changes to src/json_tag.c.

111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
  cson_object_set(pay, "value", (zValue&&*zValue)
                  ? json_new_string(zValue)
                  : cson_value_null());
  cson_object_set(pay, "propagate", cson_value_new_bool(fPropagate));
  cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
  {
    Blob uu = empty_blob;

    blob_append(&uu, zName, -1);
    int const rc = name_to_uuid(&uu, 9, "*");
    if(0!=rc){
      json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!");
      blob_reset(&uu);
      goto error;
    }
    cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
    blob_reset(&uu);







>

|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  cson_object_set(pay, "value", (zValue&&*zValue)
                  ? json_new_string(zValue)
                  : cson_value_null());
  cson_object_set(pay, "propagate", cson_value_new_bool(fPropagate));
  cson_object_set(pay, "raw", cson_value_new_bool(fRaw));
  {
    Blob uu = empty_blob;
    int rc;
    blob_append(&uu, zName, -1);
    rc = name_to_uuid(&uu, 9, "*");
    if(0!=rc){
      json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!");
      blob_reset(&uu);
      goto error;
    }
    cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu)));
    blob_reset(&uu);

Changes to src/json_timeline.c.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
278
279
280
281
282
283
284

285
286
287
288
289



290
291
292
293
294
295
296
297
298
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
*/
cson_value * json_page_timeline(){
#if 0
  /* The original timeline code does not require 'h' access,
     but it arguably should. For JSON mode i think one could argue
     that History permissions are required.
  */
  if(! g.perm.History && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
    return NULL;
  }
#endif
  return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
}

................................................................................
    blob_appendf(pSql,"LIMIT %d ",limit);
  }
  if(pPayload){
    cson_object_set(pPayload, "limit", json_new_int(limit));
  }
  return 0;
}


/*
** If any files are associated with the given rid, a JSON array
** containing information about them is returned (and is owned by the
** caller). If no files are associated with it then NULL is returned.



*/
cson_value * json_get_changed_files(int rid){
  cson_value * rowsV = NULL;
  cson_array * rows = NULL;
  Stmt q = empty_Stmt;
  db_prepare(&q, 
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
           "       (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
................................................................................
    if(!rowsV){
      rowsV = cson_value_new_array();
      rows = cson_value_get_array(rowsV);
    }
    cson_array_append( rows, rowV );
    cson_object_set(row, "name", json_new_string(db_column_text(&q,2)));
    cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
    if(!isNew){
      cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
    }
    cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));

    cson_object_set(row, "state",
                    json_new_string(json_artifact_status_to_string(isNew,isDel)));
    zDownload = mprintf("/raw/%s?name=%s",
................................................................................
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  char showFiles = -1/*magic number*/;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;
  Blob sql = empty_blob;
  if( !g.perm.History ){
    /* Reminder to self: HTML impl requires 'o' (Read)
       rights.
    */
    json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
    return NULL;
  }
  showFiles = json_find_option_bool("files",NULL,"f",0);







|







 







>





>
>
>

|







 







|







 







|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
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
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
*/
cson_value * json_page_timeline(){
#if 0
  /* The original timeline code does not require 'h' access,
     but it arguably should. For JSON mode i think one could argue
     that History permissions are required.
  */
  if(! g.perm.Hyperlink && !g.perm.Read ){
    json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
    return NULL;
  }
#endif
  return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
}

................................................................................
    blob_appendf(pSql,"LIMIT %d ",limit);
  }
  if(pPayload){
    cson_object_set(pPayload, "limit", json_new_int(limit));
  }
  return 0;
}


/*
** If any files are associated with the given rid, a JSON array
** containing information about them is returned (and is owned by the
** caller). If no files are associated with it then NULL is returned.
**
** flags may optionally be a bitmask of json_get_changed_files flags,
** or 0 for defaults.
*/
cson_value * json_get_changed_files(int rid, int flags){
  cson_value * rowsV = NULL;
  cson_array * rows = NULL;
  Stmt q = empty_Stmt;
  db_prepare(&q, 
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
           "       (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
................................................................................
    if(!rowsV){
      rowsV = cson_value_new_array();
      rows = cson_value_get_array(rowsV);
    }
    cson_array_append( rows, rowV );
    cson_object_set(row, "name", json_new_string(db_column_text(&q,2)));
    cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3)));
    if(!isNew && (flags & json_get_changed_files_ELIDE_PARENT)){
      cson_object_set(row, "parent", json_new_string(db_column_text(&q,4)));
    }
    cson_object_set(row, "size", json_new_int(db_column_int(&q,5)));

    cson_object_set(row, "state",
                    json_new_string(json_artifact_status_to_string(isNew,isDel)));
    zDownload = mprintf("/raw/%s?name=%s",
................................................................................
  cson_value * listV = NULL;
  cson_array * list = NULL;
  int check = 0;
  char showFiles = -1/*magic number*/;
  Stmt q = empty_Stmt;
  char warnRowToJsonFailed = 0;
  Blob sql = empty_blob;
  if( !g.perm.Hyperlink ){
    /* Reminder to self: HTML impl requires 'o' (Read)
       rights.
    */
    json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
    return NULL;
  }
  showFiles = json_find_option_bool("files",NULL,"f",0);

Changes to src/json_user.c.

354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
401
402
403
404
405
406
407

408
409
410
411
412
413
414

415
416
417
418
419
420
421
  puts(blob_str(&sql));
  cson_output_FILE( cson_object_value(pUser), stdout, NULL );
#endif
  db_prepare(&q, "%s", blob_str(&sql));
  db_exec(&q);
  db_finalize(&q);
#if TRY_LOGIN_GROUP
  if( zPW || forceLogout ){
    Blob groupSql = empty_blob;
    char * zErr = NULL;
    blob_appendf(&groupSql,
      "INSERT INTO user(login)"
      "  SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
      zName, zName
    );
................................................................................
     a JSON form of it... */
  cson_object * u = cson_new_object();
  char const * str = NULL;
  char b = -1;
  int i = -1;
  int uid = -1;
  cson_value * payload = NULL;

#define PROP(LK,SK) str = json_find_option_cstr(LK,NULL,SK);     \
  if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0
  PROP("name","n");
  PROP("password","p");
  PROP("info","i");
  PROP("capabilities","c");
#undef PROP

#define PROP(LK,DFLT) b = json_find_option_bool(LK,NULL,NULL,DFLT);     \
  if(DFLT!=b){ cson_object_set(u, LK, cson_value_new_bool(b)); } (void)0
  PROP("forceLogout",-1);
#undef PROP

#define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT);   \
  if(DFLT != i){ cson_object_set(u, LK, cson_value_new_integer(i)); } (void)0







|







 







>







>







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
  puts(blob_str(&sql));
  cson_output_FILE( cson_object_value(pUser), stdout, NULL );
#endif
  db_prepare(&q, "%s", blob_str(&sql));
  db_exec(&q);
  db_finalize(&q);
#if TRY_LOGIN_GROUP
  if( zPW || cson_value_get_bool(forceLogout) ){
    Blob groupSql = empty_blob;
    char * zErr = NULL;
    blob_appendf(&groupSql,
      "INSERT INTO user(login)"
      "  SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
      zName, zName
    );
................................................................................
     a JSON form of it... */
  cson_object * u = cson_new_object();
  char const * str = NULL;
  char b = -1;
  int i = -1;
  int uid = -1;
  cson_value * payload = NULL;
  /* String properties... */
#define PROP(LK,SK) str = json_find_option_cstr(LK,NULL,SK);     \
  if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0
  PROP("name","n");
  PROP("password","p");
  PROP("info","i");
  PROP("capabilities","c");
#undef PROP
  /* Boolean properties... */
#define PROP(LK,DFLT) b = json_find_option_bool(LK,NULL,NULL,DFLT);     \
  if(DFLT!=b){ cson_object_set(u, LK, cson_value_new_bool(b)); } (void)0
  PROP("forceLogout",-1);
#undef PROP

#define PROP(LK,DFLT) i = json_find_option_int(LK,NULL,NULL,DFLT);   \
  if(DFLT != i){ cson_object_set(u, LK, cson_value_new_integer(i)); } (void)0

Changes to src/json_wiki.c.

1
2
3
4
5
6
7
8
9
10
..
46
47
48
49
50
51
52
53
54
55





56
57
58
59
60
61
62
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
105
106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
#ifdef FOSSIL_ENABLE_JSON
/*
** Copyright (c) 2011 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
................................................................................


/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki(){
  return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
}






char * json_wiki_get_uuid_for_rid( int rid )
{
  return db_text(NULL,
             "SELECT b.uuid FROM tag t, tagxref x, blob b"
             " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
             " AND b.rid=x.rid AND b.rid=%d"
             " ORDER BY x.mtime DESC LIMIT 1",
................................................................................
  Manifest * pWiki = NULL;
  if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
    json_set_err( FSL_JSON_E_UNKNOWN,
                  "Error reading wiki page from manifest (rid=%d).",
                  rid );
    return NULL;
  }else{
    /*char const * zFormat = NULL;*/
    unsigned int len = 0;
    cson_object * pay = cson_new_object();
    char const * zBody = pWiki->zWiki;
    char const * zFormat = NULL;
    char * zUuid = json_wiki_get_uuid_for_rid(rid);
    cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
    cson_object_set(pay,"uuid",json_new_string(zUuid));
................................................................................
    cson_object_set(pay,FossilJsonKeys.timestamp,
                    json_julian_to_timestamp(pWiki->rDate));
    if(0 == contentFormat){
      cson_object_set(pay,"size",
                      json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
    }else{
      if( contentFormat>0 ){/*HTML-ize it*/
        zFormat = "html";
        Blob content = empty_blob;
        Blob raw = empty_blob;

        if(zBody && *zBody){
          blob_append(&raw,zBody,-1);
          wiki_convert(&raw,&content,0);
          len = (unsigned int)blob_size(&content);
        }
        cson_object_set(pay,"size",json_new_int((cson_int_t)len));
        cson_object_set(pay,"content",
................................................................................
  int argPos = g.json.dispatchDepth;
  int r1 = 0, r2 = 0;
  Manifest * pW1 = NULL, *pW2 = NULL;
  Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
  char const * zErrTag = NULL;
  int diffFlags;
  char * zUuid = NULL;
  if( !g.perm.History ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'h' permissions.");
    return NULL;
  }

  
  zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );


|







 







|


>
>
>
>
>







 







<







 







<


>







 







|







1
2
3
4
5
6
7
8
9
10
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
86
87
88
89
90
91
92

93
94
95
96
97
98
99
...
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
#ifdef FOSSIL_ENABLE_JSON
/*
** Copyright (c) 2011-12 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
................................................................................


/*
** Implements the /json/wiki family of pages/commands.
**
*/
cson_value * json_page_wiki(){
  return json_page_dispatch_helper(JsonPageDefs_Wiki);
}

/*
** Returns the UUID for the given wiki blob RID, or NULL if not
** found. The returned string is allocated via db_text() and must be
** free()d by the caller.
*/
char * json_wiki_get_uuid_for_rid( int rid )
{
  return db_text(NULL,
             "SELECT b.uuid FROM tag t, tagxref x, blob b"
             " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
             " AND b.rid=x.rid AND b.rid=%d"
             " ORDER BY x.mtime DESC LIMIT 1",
................................................................................
  Manifest * pWiki = NULL;
  if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI)) ){
    json_set_err( FSL_JSON_E_UNKNOWN,
                  "Error reading wiki page from manifest (rid=%d).",
                  rid );
    return NULL;
  }else{

    unsigned int len = 0;
    cson_object * pay = cson_new_object();
    char const * zBody = pWiki->zWiki;
    char const * zFormat = NULL;
    char * zUuid = json_wiki_get_uuid_for_rid(rid);
    cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
    cson_object_set(pay,"uuid",json_new_string(zUuid));
................................................................................
    cson_object_set(pay,FossilJsonKeys.timestamp,
                    json_julian_to_timestamp(pWiki->rDate));
    if(0 == contentFormat){
      cson_object_set(pay,"size",
                      json_new_int((cson_int_t)(zBody?strlen(zBody):0)));
    }else{
      if( contentFormat>0 ){/*HTML-ize it*/

        Blob content = empty_blob;
        Blob raw = empty_blob;
        zFormat = "html";
        if(zBody && *zBody){
          blob_append(&raw,zBody,-1);
          wiki_convert(&raw,&content,0);
          len = (unsigned int)blob_size(&content);
        }
        cson_object_set(pay,"size",json_new_int((cson_int_t)len));
        cson_object_set(pay,"content",
................................................................................
  int argPos = g.json.dispatchDepth;
  int r1 = 0, r2 = 0;
  Manifest * pW1 = NULL, *pW2 = NULL;
  Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
  char const * zErrTag = NULL;
  int diffFlags;
  char * zUuid = NULL;
  if( !g.perm.Hyperlink ){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'h' permissions.");
    return NULL;
  }

  
  zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );

Changes to src/login.c.

462
463
464
465
466
467
468

469
470
471
472
473
474
475
...
559
560
561
562
563
564
565



566
567

568
569
570
571
572
573
574
575
...
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
...
759
760
761
762
763
764
765


766
767
768
769
770
771
772

773
774
775
776
777
778
779
...
902
903
904
905
906
907
908
909

910
911














912
913
914
915
916
917
918
...
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
....
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
....
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
** line on the title bar.  The "my" page was never completed so it is now
** removed.  Use this page as a placeholder in older installations.
*/
void login_page(void){
  const char *zUsername, *zPasswd;
  const char *zNew1, *zNew2;
  const char *zAnonPw = 0;

  int anonFlag;
  char *zErrMsg = "";
  int uid;                     /* User id loged in user */
  char *zSha1Pw;
  const char *zIpAddr;         /* IP address of requestor */

  login_check_credentials();
................................................................................
      */
      login_set_user_cookie(zUsername, uid, NULL);
      redirect_to_g();
    }
  }
  style_header("Login/Logout");
  @ %s(zErrMsg)



  @ <form action="login" method="post">
  if( P("g") ){

    @ <input type="hidden" name="g" value="%h(P("g"))" />
  }
  @ <table class="login_out">
  @ <tr>
  @   <td class="login_out_label">User ID:</td>
  if( anonFlag ){
    @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
  }else{
................................................................................
  @ <tr>
  @   <td></td>
  @   <td><input type="submit" name="in" value="Login"
  @        onClick="chngAction(this.form)" /></td>
  @ </tr>
  @ </table>
  @ <script type="text/JavaScript">
  @   document.getElementById('u').focus()
  @   function chngAction(form){
  if( g.sslNotAvailable==0
   && memcmp(g.zBaseURL,"https:",6)!=0
   && db_get_boolean("https-login",0)
  ){
     char *zSSL = mprintf("https:%s", &g.zBaseURL[5]);
     @  if( form.u.value!="anonymous" ){
................................................................................
    @ Visitors may enter <b>anonymous</b> as the user-ID with
    @ the 8-character hexadecimal password shown below:</p>
    @ <div class="captcha"><table class="captcha"><tr><td><pre>
    @ %s(zCaptcha)
    @ </pre></td></tr></table>
    if( bAutoCaptcha ) {
        @ <input type="button" value="Fill out captcha"
        @  onclick="document.getElementById('u').value='anonymous';
        @           document.getElementById('p').value='%s(zDecoded)';" />
    }
    @ </div>
    free(zCaptcha);
  }
  if( g.zLogin ){
    @ <hr />
    @ <p>To log off the system (and delete your login cookie)
................................................................................
}

/*
** This routine examines the login cookie to see if it exists and and
** is valid.  If the login cookie checks out, it then sets global
** variables appropriately.  Global variables set include g.userUid
** and g.zLogin and the g.perm family of permission booleans.


*/
void login_check_credentials(void){
  int uid = 0;                  /* User id */
  const char *zCookie;          /* Text of the login cookie */
  const char *zIpAddr;          /* Raw IP address of the requestor */
  char *zRemoteAddr;            /* Abbreviated IP address of the requestor */
  const char *zCap = 0;         /* Capability string */


  /* Only run this check once.  */
  if( g.userUid!=0 ) return;

  sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
		  constant_time_cmp_function, 0, 0);

................................................................................
  if( fossil_strcmp(g.zLogin,"nobody")==0 ){
    g.zLogin = 0;
  }

  /* Set the capabilities */
  login_replace_capabilities(zCap, 0);
  login_set_anon_nobody_capabilities();
  if( zCap[0] && !g.perm.History && db_get_boolean("auto-enable-hyperlinks",1)

      && isHuman(P("HTTP_USER_AGENT")) ){
    g.perm.History = 1;














  }
}

/*
** Memory of settings
*/
static int login_anon_once = 1;
................................................................................
  if(NULL==zCap){
    return;
  }
  for(i=0; zCap[i]; i++){
    switch( zCap[i] ){
      case 's':   g.perm.Setup = 1;  /* Fall thru into Admin */
      case 'a':   g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
                              g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
                              g.perm.ApndWiki = g.perm.History = g.perm.Clone = 
                              g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
                              g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
                              /* Fall thru into Read/Write */
      case 'i':   g.perm.Read = g.perm.Write = 1;                     break;
      case 'o':   g.perm.Read = 1;                                 break;
      case 'z':   g.perm.Zip = 1;                                  break;

      case 'd':   g.perm.Delete = 1;                               break;
      case 'h':   g.perm.History = 1;                              break;
      case 'g':   g.perm.Clone = 1;                                break;
      case 'p':   g.perm.Password = 1;                             break;

      case 'j':   g.perm.RdWiki = 1;                               break;
      case 'k':   g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1;    break;
      case 'm':   g.perm.ApndWiki = 1;                             break;
      case 'f':   g.perm.NewWiki = 1;                              break;
................................................................................
      case 'a':  rc = g.perm.Admin;     break;
      case 'b':  rc = g.perm.Attach;    break;
      case 'c':  rc = g.perm.ApndTkt;   break;
      case 'd':  rc = g.perm.Delete;    break;
      case 'e':  rc = g.perm.RdAddr;    break;
      case 'f':  rc = g.perm.NewWiki;   break;
      case 'g':  rc = g.perm.Clone;     break;
      case 'h':  rc = g.perm.History;   break;
      case 'i':  rc = g.perm.Write;     break;
      case 'j':  rc = g.perm.RdWiki;    break;
      case 'k':  rc = g.perm.WrWiki;    break;
      /* case 'l': */
      case 'm':  rc = g.perm.ApndWiki;  break;
      case 'n':  rc = g.perm.NewTkt;    break;
      case 'o':  rc = g.perm.Read;      break;
      case 'p':  rc = g.perm.Password;  break;
      /* case 'q': */
      case 'r':  rc = g.perm.RdTkt;     break;
      case 's':  rc = g.perm.Setup;     break;
................................................................................
    cgi_redirect(mprintf("login?g=%T", zUrl));
    /* NOTREACHED */
    assert(0);
  }
}

/*
** Call this routine if the user lacks okHistory permission.  If
** the anonymous user has okHistory permission, then paint a mesage
** to inform the user that much more information is available by
** logging in as anonymous.
*/
void login_anonymous_available(void){
  if( !g.perm.History &&
      db_exists("SELECT 1 FROM user"
                " WHERE login='anonymous'"
                "   AND cap LIKE '%%h%%'") ){
    const char *zUrl = PD("REQUEST_URI", "index");
    @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
    @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
    @ to enable hyperlinks.</p>
  }
}

/*
** While rendering a form, call this routine to add the Anti-CSRF token
** as a hidden element of the form.







>







 







>
>
>

<
>
|







 







|







 







<
|







 







>
>







>







 







|
>

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







 







|
|
|
|
|





|







 







|



<







 







|
|




|





|







462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
...
560
561
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
578
579
...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
633
634
635
636
637
638
639

640
641
642
643
644
645
646
647
...
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
...
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
...
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
....
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
....
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
** line on the title bar.  The "my" page was never completed so it is now
** removed.  Use this page as a placeholder in older installations.
*/
void login_page(void){
  const char *zUsername, *zPasswd;
  const char *zNew1, *zNew2;
  const char *zAnonPw = 0;
  const char *zGoto = P("g");
  int anonFlag;
  char *zErrMsg = "";
  int uid;                     /* User id loged in user */
  char *zSha1Pw;
  const char *zIpAddr;         /* IP address of requestor */

  login_check_credentials();
................................................................................
      */
      login_set_user_cookie(zUsername, uid, NULL);
      redirect_to_g();
    }
  }
  style_header("Login/Logout");
  @ %s(zErrMsg)
  if( zGoto && P("anon")==0 ){
    @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
  }
  @ <form action="login" method="post">

  if( zGoto ){
    @ <input type="hidden" name="g" value="%h(zGoto)" />
  }
  @ <table class="login_out">
  @ <tr>
  @   <td class="login_out_label">User ID:</td>
  if( anonFlag ){
    @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
  }else{
................................................................................
  @ <tr>
  @   <td></td>
  @   <td><input type="submit" name="in" value="Login"
  @        onClick="chngAction(this.form)" /></td>
  @ </tr>
  @ </table>
  @ <script type="text/JavaScript">
  @   gebi('u').focus()
  @   function chngAction(form){
  if( g.sslNotAvailable==0
   && memcmp(g.zBaseURL,"https:",6)!=0
   && db_get_boolean("https-login",0)
  ){
     char *zSSL = mprintf("https:%s", &g.zBaseURL[5]);
     @  if( form.u.value!="anonymous" ){
................................................................................
    @ Visitors may enter <b>anonymous</b> as the user-ID with
    @ the 8-character hexadecimal password shown below:</p>
    @ <div class="captcha"><table class="captcha"><tr><td><pre>
    @ %s(zCaptcha)
    @ </pre></td></tr></table>
    if( bAutoCaptcha ) {
        @ <input type="button" value="Fill out captcha"

        @  onclick="gebi('u').value='anonymous'; gebi('p').value='%s(zDecoded)';" />
    }
    @ </div>
    free(zCaptcha);
  }
  if( g.zLogin ){
    @ <hr />
    @ <p>To log off the system (and delete your login cookie)
................................................................................
}

/*
** This routine examines the login cookie to see if it exists and and
** is valid.  If the login cookie checks out, it then sets global
** variables appropriately.  Global variables set include g.userUid
** and g.zLogin and the g.perm family of permission booleans.
**
** If the 
*/
void login_check_credentials(void){
  int uid = 0;                  /* User id */
  const char *zCookie;          /* Text of the login cookie */
  const char *zIpAddr;          /* Raw IP address of the requestor */
  char *zRemoteAddr;            /* Abbreviated IP address of the requestor */
  const char *zCap = 0;         /* Capability string */
  const char *zPublicPages = 0; /* GLOB patterns of public pages */

  /* Only run this check once.  */
  if( g.userUid!=0 ) return;

  sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
		  constant_time_cmp_function, 0, 0);

................................................................................
  if( fossil_strcmp(g.zLogin,"nobody")==0 ){
    g.zLogin = 0;
  }

  /* Set the capabilities */
  login_replace_capabilities(zCap, 0);
  login_set_anon_nobody_capabilities();
  if( zCap[0] && !g.perm.Hyperlink
   && db_get_boolean("auto-hyperlink",1)
      && isHuman(P("HTTP_USER_AGENT")) ){
    g.perm.Hyperlink = 1;
    g.javascriptHyperlink = 1;
  }

  /* If the public-pages glob pattern is defined and REQUEST_URI matches
  ** one of the globs in public-pages, then also add in all default-perms
  ** permissions.
  */
  zPublicPages = db_get("public-pages",0);
  if( zPublicPages!=0 ){
    Glob *pGlob = glob_create(zPublicPages);
    if( glob_match(pGlob, PD("REQUEST_URI","no-match")) ){
      login_set_capabilities(db_get("default-perms","u"), 0);
    }
    glob_free(pGlob);
  }
}

/*
** Memory of settings
*/
static int login_anon_once = 1;
................................................................................
  if(NULL==zCap){
    return;
  }
  for(i=0; zCap[i]; i++){
    switch( zCap[i] ){
      case 's':   g.perm.Setup = 1;  /* Fall thru into Admin */
      case 'a':   g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
                           g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
                           g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone = 
                           g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
                           g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
                           /* Fall thru into Read/Write */
      case 'i':   g.perm.Read = g.perm.Write = 1;                     break;
      case 'o':   g.perm.Read = 1;                                 break;
      case 'z':   g.perm.Zip = 1;                                  break;

      case 'd':   g.perm.Delete = 1;                               break;
      case 'h':   g.perm.Hyperlink = 1;                            break;
      case 'g':   g.perm.Clone = 1;                                break;
      case 'p':   g.perm.Password = 1;                             break;

      case 'j':   g.perm.RdWiki = 1;                               break;
      case 'k':   g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1;    break;
      case 'm':   g.perm.ApndWiki = 1;                             break;
      case 'f':   g.perm.NewWiki = 1;                              break;
................................................................................
      case 'a':  rc = g.perm.Admin;     break;
      case 'b':  rc = g.perm.Attach;    break;
      case 'c':  rc = g.perm.ApndTkt;   break;
      case 'd':  rc = g.perm.Delete;    break;
      case 'e':  rc = g.perm.RdAddr;    break;
      case 'f':  rc = g.perm.NewWiki;   break;
      case 'g':  rc = g.perm.Clone;     break;
      case 'h':  rc = g.perm.Hyperlink; break;
      case 'i':  rc = g.perm.Write;     break;
      case 'j':  rc = g.perm.RdWiki;    break;
      case 'k':  rc = g.perm.WrWiki;    break;

      case 'm':  rc = g.perm.ApndWiki;  break;
      case 'n':  rc = g.perm.NewTkt;    break;
      case 'o':  rc = g.perm.Read;      break;
      case 'p':  rc = g.perm.Password;  break;
      /* case 'q': */
      case 'r':  rc = g.perm.RdTkt;     break;
      case 's':  rc = g.perm.Setup;     break;
................................................................................
    cgi_redirect(mprintf("login?g=%T", zUrl));
    /* NOTREACHED */
    assert(0);
  }
}

/*
** Call this routine if the user lacks g.perm.Hyperlink permission.  If
** the anonymous user has Hyperlink permission, then paint a mesage
** to inform the user that much more information is available by
** logging in as anonymous.
*/
void login_anonymous_available(void){
  if( !g.perm.Hyperlink &&
      db_exists("SELECT 1 FROM user"
                " WHERE login='anonymous'"
                "   AND cap LIKE '%%h%%'") ){
    const char *zUrl = PD("REQUEST_URI", "index");
    @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
    @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
    @ to enable hyperlinks.</p>
  }
}

/*
** While rendering a form, call this routine to add the Anti-CSRF token
** as a hidden element of the form.

Changes to src/main.c.

22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
...
448
449
450
451
452
453
454

455
456
457
458
459
460
461
462
463
464



465
466
467
468
469
470
471
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
....
1085
1086
1087
1088
1089
1090
1091











1092
1093
1094
1095
1096
1097
1098
....
1133
1134
1135
1136
1137
1138
1139
1140
1141



1142
1143
1144
1145
1146
1147
1148
....
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
#include "main.h"
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h> /* atexit() */



#if INTERFACE
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */
#  include "json_detail.h"
#endif
#ifdef FOSSIL_ENABLE_TCL
#include "tcl.h"
................................................................................
  char Setup;            /* s: use Setup screens on web interface */
  char Admin;            /* a: administrative permission */
  char Delete;           /* d: delete wiki or tickets */
  char Password;         /* p: change password */
  char Query;            /* q: create new reports */
  char Write;            /* i: xfer inbound. checkin */
  char Read;             /* o: xfer outbound. checkout */
  char History;          /* h: access historical information. */
  char Clone;            /* g: clone */
  char RdWiki;           /* j: view wiki via web */
  char NewWiki;          /* f: create new wiki via web */
  char ApndWiki;         /* m: append to wiki via web */
  char WrWiki;           /* k: edit wiki via web */
  char RdTkt;            /* r: view tickets via web */
  char NewTkt;           /* n: create new tickets */
................................................................................
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int isHTTP;             /* True if running in server/CGI modes, else assume CLI. */


  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
  char *urlName;          /* Hostname for http: or filename for file: */
  char *urlHostname;      /* The HOST: parameter on http headers */
  char *urlProtocol;      /* "http" or "https" */
................................................................................
      cson_value * v;
      cson_object * o;
    } param;
    struct {
      cson_value * v;
      cson_object * o;
    } reqPayload;              /* request payload object (if any) */
    struct {                   /* response warnings */
      cson_value * v;
      cson_array * a;
    } warnings;
  } json;
#endif /* FOSSIL_ENABLE_JSON */
};

/*
** Macro for debugging:
*/
................................................................................
    fossil_print(
       "Usage: %s COMMAND ...\n"
       "   or: %s help           -- for a list of common commands\n"
       "   or: %s help COMMMAND  -- for help with the named command\n",
       argv[0], argv[0], argv[0]);
    fossil_exit(1);
  }else{

    g.isHTTP = 0;
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);



    if( find_option("help",0,0)!=0 ){
      /* --help anywhere on the command line is translated into
      ** "fossil help argv[1] argv[2]..." */
      int i;
      char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
      for(i=1; i<g.argc; i++) zNewArgv[i+1] = argv[i];
      zNewArgv[i+1] = 0;
................................................................................
  else
#endif
  {
    if( g.cgiOutput && once ){
      once = 0;
      cgi_printf("<p class=\"generalError\">%h</p>", z);
      cgi_reply();
    }else{
      char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z);
      fossil_puts(zOut, 1);
    }
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
................................................................................
  else
#endif
  {
    if( g.cgiOutput ){
      g.cgiOutput = 0;
      cgi_printf("<p class=\"generalError\">%h</p>", z);
      cgi_reply();
    }else{
      char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
      fossil_puts(zOut, 1);
    }
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
................................................................................
  if( fossil_stricmp(zMode,"on")==0 ){
    g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
    g.zTop = &g.zBaseURL[8+strlen(zHost)];
  }else{
    g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
    g.zTop = &g.zBaseURL[7+strlen(zHost)];
  }











}

/*
** Send an HTTP redirect back to the designated Index Page.
*/
NORETURN void fossil_redirect_home(void){
  cgi_redirectf("%s%s", g.zTop, db_get("index-page", "/index"));
................................................................................
      }
      zDir[i] = '/';
      zRepo = &zDir[i];
    }
    if( stat(zRepo, &sStat)!=0 ){
      fossil_fatal("cannot stat() repository: %s", zRepo);
    }
    setgid(sStat.st_gid);
    setuid(sStat.st_uid);



    if( g.db!=0 ){
      db_close(1);
      db_open_repository(zRepo);
    }
  }
#endif
  return zRepo;
................................................................................
#ifdef FOSSIL_ENABLE_JSON
  /*
  ** Workaround to allow us to customize some following behaviour for
  ** JSON mode.  The problem is, we don't always know if we're in JSON
  ** mode at this point (namely, for GET mode we don't know but POST
  ** we do), so we snoop g.zPath and cheat a bit.
  */
  if( g.zPath && (0==strcmp("json",g.zPath)) ){
    g.json.isJsonMode = 1;
  }
#endif
  if( g.zExtra ){
    /* CGI parameters get this treatment elsewhere, but places like getfile
    ** will use g.zExtra directly.
    ** Reminder: the login mechanism uses 'name' differently, and may







|
>
>







 







|







 







|
>







 







|
<
<
<







 







>










>
>
>







 







|







 







|







 







>
>
>
>
>
>
>
>
>
>
>







 







|
|
>
>
>







 







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
243
244
245
246
247
248
249
250



251
252
253
254
255
256
257
...
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
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
....
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
....
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
....
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
#include "main.h"
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h> /* atexit() */
#if !defined(_WIN32)
#  include <errno.h> /* errno global */
#endif
#if INTERFACE
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */
#  include "json_detail.h"
#endif
#ifdef FOSSIL_ENABLE_TCL
#include "tcl.h"
................................................................................
  char Setup;            /* s: use Setup screens on web interface */
  char Admin;            /* a: administrative permission */
  char Delete;           /* d: delete wiki or tickets */
  char Password;         /* p: change password */
  char Query;            /* q: create new reports */
  char Write;            /* i: xfer inbound. checkin */
  char Read;             /* o: xfer outbound. checkout */
  char Hyperlink;        /* h: enable the display of hyperlinks */
  char Clone;            /* g: clone */
  char RdWiki;           /* j: view wiki via web */
  char NewWiki;          /* f: create new wiki via web */
  char ApndWiki;         /* m: append to wiki via web */
  char WrWiki;           /* k: edit wiki via web */
  char RdTkt;            /* r: view tickets via web */
  char NewTkt;           /* n: create new tickets */
................................................................................
  FILE *httpIn;           /* Accept HTTP input from here */
  FILE *httpOut;          /* Send HTTP output here */
  int xlinkClusterOnly;   /* Set when cloning.  Only process clusters */
  int fTimeFormat;        /* 1 for UTC.  2 for localtime.  0 not yet selected */
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  char isHTTP;            /* True if erver/CGI modes, else assume CLI. */
  char javascriptHyperlink; /* If true, set href= using script, not HTML */

  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
  char *urlName;          /* Hostname for http: or filename for file: */
  char *urlHostname;      /* The HOST: parameter on http headers */
  char *urlProtocol;      /* "http" or "https" */
................................................................................
      cson_value * v;
      cson_object * o;
    } param;
    struct {
      cson_value * v;
      cson_object * o;
    } reqPayload;              /* request payload object (if any) */
    cson_array * warnings;     /* response warnings */



  } json;
#endif /* FOSSIL_ENABLE_JSON */
};

/*
** Macro for debugging:
*/
................................................................................
    fossil_print(
       "Usage: %s COMMAND ...\n"
       "   or: %s help           -- for a list of common commands\n"
       "   or: %s help COMMMAND  -- for help with the named command\n",
       argv[0], argv[0], argv[0]);
    fossil_exit(1);
  }else{
    const char *zChdir = find_option("chdir",0,1);
    g.isHTTP = 0;
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
    g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
    g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
    g.zLogin = find_option("user", "U", 1);
    g.zSSLIdentity = find_option("ssl-identity", 0, 1);
    if( zChdir && chdir(zChdir) ){
      fossil_fatal("unable to change directories to %s", zChdir);
    }
    if( find_option("help",0,0)!=0 ){
      /* --help anywhere on the command line is translated into
      ** "fossil help argv[1] argv[2]..." */
      int i;
      char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) );
      for(i=1; i<g.argc; i++) zNewArgv[i+1] = argv[i];
      zNewArgv[i+1] = 0;
................................................................................
  else
#endif
  {
    if( g.cgiOutput && once ){
      once = 0;
      cgi_printf("<p class=\"generalError\">%h</p>", z);
      cgi_reply();
    }else if( !g.fQuiet ){
      char *zOut = mprintf("%s: %s\n", fossil_nameofexe(), z);
      fossil_puts(zOut, 1);
    }
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
................................................................................
  else
#endif
  {
    if( g.cgiOutput ){
      g.cgiOutput = 0;
      cgi_printf("<p class=\"generalError\">%h</p>", z);
      cgi_reply();
    }else if( !g.fQuiet ){
      char *zOut = mprintf("\r%s: %s\n", fossil_nameofexe(), z);
      fossil_puts(zOut, 1);
    }
  }
  free(z);
  db_force_rollback();
  fossil_exit(rc);
................................................................................
  if( fossil_stricmp(zMode,"on")==0 ){
    g.zBaseURL = mprintf("https://%s%.*s", zHost, i, zCur);
    g.zTop = &g.zBaseURL[8+strlen(zHost)];
  }else{
    g.zBaseURL = mprintf("http://%s%.*s", zHost, i, zCur);
    g.zTop = &g.zBaseURL[7+strlen(zHost)];
  }
  if( db_is_writeable("repository") ){
    if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
      db_multi_exec("INSERT INTO config(name,value,mtime)"
                    "VALUES('baseurl:%q',1,now())", g.zBaseURL);
    }else{
      db_optional_sql("repository",
           "REPLACE INTO config(name,value,mtime)"
           "VALUES('baseurl:%q',1,now())", g.zBaseURL
      );
    }
  }
}

/*
** Send an HTTP redirect back to the designated Index Page.
*/
NORETURN void fossil_redirect_home(void){
  cgi_redirectf("%s%s", g.zTop, db_get("index-page", "/index"));
................................................................................
      }
      zDir[i] = '/';
      zRepo = &zDir[i];
    }
    if( stat(zRepo, &sStat)!=0 ){
      fossil_fatal("cannot stat() repository: %s", zRepo);
    }
    i = setgid(sStat.st_gid);
    i = i || setuid(sStat.st_uid);
    if(i){
      fossil_fatal("setgid/uid() failed with errno %d", errno);
    }
    if( g.db!=0 ){
      db_close(1);
      db_open_repository(zRepo);
    }
  }
#endif
  return zRepo;
................................................................................
#ifdef FOSSIL_ENABLE_JSON
  /*
  ** Workaround to allow us to customize some following behaviour for
  ** JSON mode.  The problem is, we don't always know if we're in JSON
  ** mode at this point (namely, for GET mode we don't know but POST
  ** we do), so we snoop g.zPath and cheat a bit.
  */
  if( !g.json.isJsonMode && g.zPath && (0==strncmp("json",g.zPath,4)) ){
    g.json.isJsonMode = 1;
  }
#endif
  if( g.zExtra ){
    /* CGI parameters get this treatment elsewhere, but places like getfile
    ** will use g.zExtra directly.
    ** Reminder: the login mechanism uses 'name' differently, and may

Changes to src/main.mk.

313
314
315
316
317
318
319

320
321
322
323
324
325
326
....
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)

	mv $(APPNAME) $(INSTALLDIR)

$(OBJDIR):
	-mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o


$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE








>







 







|


|


|



|

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
....
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
APPNAME = fossil$(E)



all:	$(OBJDIR) $(APPNAME)

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

$(OBJDIR):
	-mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................
$(OBJDIR)/sqlite3.o:	$(SRCDIR)/sqlite3.c
	$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o

$(OBJDIR)/shell.o:	$(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
	$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o


$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE

Changes to src/makemake.tcl.

178
179
180
181
182
183
184

185
186
187
188
189
190
191
...
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
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
...
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
...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
writeln "APPNAME = $name\$(E)"
writeln "\n"

writeln {
all:	$(OBJDIR) $(APPNAME)

install:	$(APPNAME)

	mv $(APPNAME) $(INSTALLDIR)

$(OBJDIR):
	-mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

set opt {}
writeln {
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
}

close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################
................................................................................
FOSSIL_TCL_SOURCE = 1

#### The directories where the zlib include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#
ZINCDIR = $(SRCDIR)/../zlib-1.2.6
ZLIBDIR = $(SRCDIR)/../zlib-1.2.6

#### 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.
#
OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1a/include
OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1a

#### 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
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
................................................................................
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = gcc -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL
TCC += -Dpqueue_insert=pqueue_insert_fossil
TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
................................................................................
writeln "\n"
writeln -nonewline "OBJ ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln "\n"
writeln "APPNAME = ${name}.exe"
writeln {TRANSLATE   = $(subst /,\\,$(OBJDIR)/translate.exe)
MAKEHEADERS = $(subst /,\\,$(OBJDIR)/makeheaders.exe)
MKINDEX     = $(subst /,\\,$(OBJDIR)/mkindex.exe)
VERSION     = $(subst /,\\,$(OBJDIR)/version.exe)
}

writeln {
all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/icon.o:	$(SRCDIR)/../win/icon.rc
	cp $(SRCDIR)/../win/icon.rc $(OBJDIR)
	windres $(OBJDIR)/icon.rc -o $(OBJDIR)/icon.o

install:	$(APPNAME)

	mv $(APPNAME) $(INSTALLDIR)

$(OBJDIR):
	mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln {ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -I$(SRCDIR) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif
}

close $output_file
#
# End of the main.mk output
##############################################################################







>







 







|


|


|




|







 







|
|






|
|







 







<







 







|
|
|
|










>







 







|


|



|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
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
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
...
415
416
417
418
419
420
421

422
423
424
425
426
427
428
...
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
...
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
writeln "APPNAME = $name\$(E)"
writeln "\n"

writeln {
all:	$(OBJDIR) $(APPNAME)

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

$(OBJDIR):
	-mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

set opt {}
writeln {
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE
}

close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################
................................................................................
FOSSIL_TCL_SOURCE = 1

#### The directories where the zlib include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "zlib-1.x.y" sub-directory of the
#    Fossil source code directory and the target zlib source directory.
#
ZINCDIR = $(SRCDIR)/../zlib-1.2.7
ZLIBDIR = $(SRCDIR)/../zlib-1.2.7

#### 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.
#
OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c

#### 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
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
................................................................................
#    the finished binary for fossil.  The BCC compiler above is used
#    for building intermediate code-generator tools.
#
TCC = gcc -Os -Wall -L$(ZLIBDIR) -I$(ZINCDIR)

# With HTTPS support
ifdef FOSSIL_ENABLE_SSL

TCC += -L$(OPENSSLLIBDIR) -I$(OPENSSLINCDIR)
endif

# With Tcl support
ifdef FOSSIL_ENABLE_TCL
ifdef FOSSIL_TCL_SOURCE
TCC += -L$(TCLSRCDIR)/win -I$(TCLSRCDIR)/generic -I$(TCLSRCDIR)/win
................................................................................
writeln "\n"
writeln -nonewline "OBJ ="
foreach s [lsort $src] {
  writeln -nonewline " \\\n \$(OBJDIR)/$s.o"
}
writeln "\n"
writeln "APPNAME = ${name}.exe"
writeln {TRANSLATE   = $(OBJDIR)/translate.exe
MAKEHEADERS = $(OBJDIR)/makeheaders.exe
MKINDEX     = $(OBJDIR)/mkindex.exe
VERSION     = $(OBJDIR)/version.exe
}

writeln {
all:	$(OBJDIR) $(APPNAME)

$(OBJDIR)/icon.o:	$(SRCDIR)/../win/icon.rc
	cp $(SRCDIR)/../win/icon.rc $(OBJDIR)
	windres $(OBJDIR)/icon.rc -o $(OBJDIR)/icon.o

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

$(OBJDIR):
	mkdir $(OBJDIR)

$(OBJDIR)/translate:	$(SRCDIR)/translate.c
	$(BCC) -o $(OBJDIR)/translate $(SRCDIR)/translate.c
................................................................................

writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
set opt {-Dmain=sqlite3_shell}
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln {ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif
}

close $output_file
#
# End of the main.mk output
##############################################################################

Changes to src/manifest.c.

972
973
974
975
976
977
978

979
980
981
982
983
984
985
  }
  blob_read_from_file(&b, g.argv[2]);
  if( g.argc>3 ) n = atoi(g.argv[3]);
  for(i=0; i<n; i++){
    Blob b2;
    blob_copy(&b2, &b);
    p = manifest_parse(&b2, 0);

    manifest_destroy(p);
  }
}

/*
** Fetch the baseline associated with the delta-manifest p.
** Return 0 on success.  If unable to parse the baseline,







>







972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
  }
  blob_read_from_file(&b, g.argv[2]);
  if( g.argc>3 ) n = atoi(g.argv[3]);
  for(i=0; i<n; i++){
    Blob b2;
    blob_copy(&b2, &b);
    p = manifest_parse(&b2, 0);
    if( p==0 ) fossil_print("FAILED!\n");
    manifest_destroy(p);
  }
}

/*
** Fetch the baseline associated with the delta-manifest p.
** Return 0 on success.  If unable to parse the baseline,

Changes to src/md5.c.

262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
        /* Append length in bits and transform */
        ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
        ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];

        MD5Transform(ctx->buf, (uint32 *)ctx->in);
        byteReverse((unsigned char *)ctx->buf, 4);
        memcpy(digest, ctx->buf, 16);
        memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
}

/*
** Convert a digest into base-16.  digest should be declared as
** "unsigned char digest[16]" in the calling function.  The MD5
** digest is stored in the first 16 bytes.  zBuf should
** be "char zBuf[33]".







|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
        /* Append length in bits and transform */
        ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
        ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];

        MD5Transform(ctx->buf, (uint32 *)ctx->in);
        byteReverse((unsigned char *)ctx->buf, 4);
        memcpy(digest, ctx->buf, 16);
        memset(ctx, 0, sizeof(*ctx));    /* In case it's sensitive */
}

/*
** Convert a digest into base-16.  digest should be declared as
** "unsigned char digest[16]" in the calling function.  The MD5
** digest is stored in the first 16 bytes.  zBuf should
** be "char zBuf[33]".

Changes to src/name.c.

158
159
160
161
162
163
164























165
166
167
168
169
170
171
       " WHERE tag.tagname='sym-%q' "
       "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
       "   AND event.objid=tagxref.rid "
       "   AND event.type GLOB '%q'"
       " ORDER BY event.mtime DESC /*sort*/",
       &zTag[4], zType
    );























    return rid;
  }

  /* symbolic-name ":" date-time */
  nTag = strlen(zTag);
  for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
  if( zTag[i]==':' && is_date(&zTag[i+1]) ){







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







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
       " WHERE tag.tagname='sym-%q' "
       "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
       "   AND event.objid=tagxref.rid "
       "   AND event.type GLOB '%q'"
       " ORDER BY event.mtime DESC /*sort*/",
       &zTag[4], zType
    );
  }
  
  /* root:TAG -> The origin of the branch */
  if( memcmp(zTag, "root:", 5)==0 ){
    Stmt q;
    int rc;
    rid = symbolic_name_to_rid(zTag+5, zType);
    db_prepare(&q,
      "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
                         " WHERE tagid=%d AND tagtype>0"
                         "   AND value=%Q AND rid=plink.pid)"
      "  FROM plink"
      " WHERE cid=:cid AND isprim",
      TAG_BRANCH, &zTag[5]
    );
    do{
      db_reset(&q);
      db_bind_int(&q, ":cid", rid);
      rc = db_step(&q);
      if( rc!=SQLITE_ROW ) break;
      rid = db_column_int(&q, 0);
    }while( db_column_int(&q, 1)==1 && rid>0 );
    db_finalize(&q);
    return rid;
  }

  /* symbolic-name ":" date-time */
  nTag = strlen(zTag);
  for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
  if( zTag[i]==':' && is_date(&zTag[i+1]) ){

Changes to src/path.c.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  PathNode *p;
  while( path.pAll ){
    p = path.pAll;
    path.pAll = p->pAll;
    fossil_free(p);
  }
  bag_clear(&path.seen);
  memset(&path, 0, sizeof(&path));
}

/*
** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
*/
static void path_reverse_path(void){
  PathNode *p;







|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  PathNode *p;
  while( path.pAll ){
    p = path.pAll;
    path.pAll = p->pAll;
    fossil_free(p);
  }
  bag_clear(&path.seen);
  memset(&path, 0, sizeof(path));
}

/*
** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
*/
static void path_reverse_path(void){
  PathNode *p;

Changes to src/pqueue.c.

20
21
22
23
24
25
26




27
28
29
30
31
32
33
..
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
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
** value.  We can insert integers with each integer tied to its
** value then extract the integer with the smallest value.
**
** The way this queue is used, we never expect it to contain more
** than 2 or 3 elements, so a simple array is sufficient as the
** implementation.  This could give worst case O(N) insert times,
** but because of the nature of the problem we expect O(1) performance.




*/
#include "config.h"
#include "pqueue.h"
#include <assert.h>


#if INTERFACE
................................................................................
  } *a;
};
#endif

/*
** Initialize a PQueue structure
*/
void pqueue_init(PQueue *p){
  memset(p, 0, sizeof(*p));
}

/*
** Destroy a PQueue.  Delete all of its content.
*/
void pqueue_clear(PQueue *p){
  free(p->a);
  pqueue_init(p);
}

/*
** Change the size of the queue so that it contains N slots
*/
static void pqueue_resize(PQueue *p, int N){
  p->a = fossil_realloc(p->a, sizeof(p->a[0])*N);
  p->sz = N;
}

/*
** Insert element e into the queue.
*/
void pqueue_insert(PQueue *p, int e, double v, void *pData){
  int i, j;
  if( p->cnt+1>p->sz ){
    pqueue_resize(p, p->cnt+5);
  }
  for(i=0; i<p->cnt; i++){
    if( p->a[i].value>v ){
      for(j=p->cnt; j>i; j--){
        p->a[j] = p->a[j-1];
      }
      break;
................................................................................
}

/*
** Extract the first element from the queue (the element with
** the smallest value) and return its ID.  Return 0 if the queue
** is empty.
*/
int pqueue_extract(PQueue *p, void **pp){
  int e, i;
  if( p->cnt==0 ){
    if( pp ) *pp = 0;
    return 0;
  }
  e = p->a[0].id;
  if( pp ) *pp = p->a[0].p;
  for(i=0; i<p->cnt-1; i++){
    p->a[i] = p->a[i+1];
  }
  p->cnt--;
  return e;
}







>
>
>
>







 







|






|

|





|







|


|







 







|













20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
** value.  We can insert integers with each integer tied to its
** value then extract the integer with the smallest value.
**
** The way this queue is used, we never expect it to contain more
** than 2 or 3 elements, so a simple array is sufficient as the
** implementation.  This could give worst case O(N) insert times,
** but because of the nature of the problem we expect O(1) performance.
**
** Compatibility note:  Some versions of OpenSSL export a symbols
** like "pqueue_insert".  This is, technically, a bug in OpenSSL.
** We work around it here by using "pqueuex_" instead of "pqueue_".
*/
#include "config.h"
#include "pqueue.h"
#include <assert.h>


#if INTERFACE
................................................................................
  } *a;
};
#endif

/*
** Initialize a PQueue structure
*/
void pqueuex_init(PQueue *p){
  memset(p, 0, sizeof(*p));
}

/*
** Destroy a PQueue.  Delete all of its content.
*/
void pqueuex_clear(PQueue *p){
  free(p->a);
  pqueuex_init(p);
}

/*
** Change the size of the queue so that it contains N slots
*/
static void pqueuex_resize(PQueue *p, int N){
  p->a = fossil_realloc(p->a, sizeof(p->a[0])*N);
  p->sz = N;
}

/*
** Insert element e into the queue.
*/
void pqueuex_insert(PQueue *p, int e, double v, void *pData){
  int i, j;
  if( p->cnt+1>p->sz ){
    pqueuex_resize(p, p->cnt+5);
  }
  for(i=0; i<p->cnt; i++){
    if( p->a[i].value>v ){
      for(j=p->cnt; j>i; j--){
        p->a[j] = p->a[j-1];
      }
      break;
................................................................................
}

/*
** Extract the first element from the queue (the element with
** the smallest value) and return its ID.  Return 0 if the queue
** is empty.
*/
int pqueuex_extract(PQueue *p, void **pp){
  int e, i;
  if( p->cnt==0 ){
    if( pp ) *pp = 0;
    return 0;
  }
  e = p->a[0].id;
  if( pp ) *pp = p->a[0].p;
  for(i=0; i<p->cnt-1; i++){
    p->a[i] = p->a[i+1];
  }
  p->cnt--;
  return e;
}

Changes to src/printf.c.

45
46
47
48
49
50
51

52
53
54
55
56
57
58
..
91
92
93
94
95
96
97

98
99
100
101
102
103
104
...
568
569
570
571
572
573
574





575
576
577
578
579
580
581
...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
#define etHTTPIZE    17 /* Make text safe for HTTP.  "/" encoded as %2f */
#define etURLIZE     18 /* Make text safe for HTTP.  "/" not encoded */
#define etFOSSILIZE  19 /* The fossil header encoding format. */
#define etPATH       20 /* Path type */
#define etWIKISTR    21 /* Wiki text rendered from a char*: %w */
#define etWIKIBLOB   22 /* Wiki text rendered from a Blob*: %W */
#define etSTRINGID   23 /* String with length limit for a UUID prefix: %S */



/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;

................................................................................
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
  {  'b',  0, 2, etBLOB,       0,  0 },
  {  'B',  0, 2, etBLOBSQL,    0,  0 },
  {  'w',  0, 2, etWIKISTR,    0,  0 },
  {  'W',  0, 2, etWIKIBLOB,   0,  0 },
  {  'h',  0, 4, etHTMLIZE,    0,  0 },

  {  't',  0, 4, etHTTPIZE,    0,  0 },  /* "/" -> "%2F" */
  {  'T',  0, 4, etURLIZE,     0,  0 },  /* "/" unchanged */
  {  'F',  0, 4, etFOSSILIZE,  0,  0 },
  {  'S',  0, 4, etSTRINGID,   0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
................................................................................
            bufpt[i]='/';
          }else{
            bufpt[i]=e[i];
          }
        }
        bufpt[length]='\0';
        break;





      }
      case etSTRINGID: {
        precision = 16;
        /* Fall through */
      }
      case etSTRING:
      case etDYNSTRING: {
................................................................................
          blob_append(pBlob,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) blob_append(pBlob,spaces,nspace);
      }
    }
    if( zExtra ){
      free(zExtra);
    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */

/*
** Print into memory obtained from malloc().
*/
char *mprintf(const char *zFormat, ...){
  va_list ap;
  char *z;
  va_start(ap,zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);







>







 







>







 







>
>
>
>
>







 







|






|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
...
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
#define etHTTPIZE    17 /* Make text safe for HTTP.  "/" encoded as %2f */
#define etURLIZE     18 /* Make text safe for HTTP.  "/" not encoded */
#define etFOSSILIZE  19 /* The fossil header encoding format. */
#define etPATH       20 /* Path type */
#define etWIKISTR    21 /* Wiki text rendered from a char*: %w */
#define etWIKIBLOB   22 /* Wiki text rendered from a Blob*: %W */
#define etSTRINGID   23 /* String with length limit for a UUID prefix: %S */
#define etROOT       24 /* String value of g.zTop: % */


/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;

................................................................................
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
  {  'b',  0, 2, etBLOB,       0,  0 },
  {  'B',  0, 2, etBLOBSQL,    0,  0 },
  {  'w',  0, 2, etWIKISTR,    0,  0 },
  {  'W',  0, 2, etWIKIBLOB,   0,  0 },
  {  'h',  0, 4, etHTMLIZE,    0,  0 },
  {  'R',  0, 0, etROOT,       0,  0 },
  {  't',  0, 4, etHTTPIZE,    0,  0 },  /* "/" -> "%2F" */
  {  'T',  0, 4, etURLIZE,     0,  0 },  /* "/" unchanged */
  {  'F',  0, 4, etFOSSILIZE,  0,  0 },
  {  'S',  0, 4, etSTRINGID,   0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
................................................................................
            bufpt[i]='/';
          }else{
            bufpt[i]=e[i];
          }
        }
        bufpt[length]='\0';
        break;
      }
      case etROOT: {
        bufpt = g.zTop ? g.zTop : "";
        length = (int)strlen(bufpt);
        break;
      }
      case etSTRINGID: {
        precision = 16;
        /* Fall through */
      }
      case etSTRING:
      case etDYNSTRING: {
................................................................................
          blob_append(pBlob,spaces,etSPACESIZE);
          nspace -= etSPACESIZE;
        }
        if( nspace>0 ) blob_append(pBlob,spaces,nspace);
      }
    }
    if( zExtra ){
      fossil_free(zExtra);
    }
  }/* End for loop over the format string */
  return errorflag ? -1 : count;
} /* End of function */

/*
** Print into memory obtained from fossil_malloc().
*/
char *mprintf(const char *zFormat, ...){
  va_list ap;
  char *z;
  va_start(ap,zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);

Changes to src/report.c.

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
...
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
...
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
...
863
864
865
866
867
868
869



870
871
872
873
874
875
876
...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
    }
    rn = db_column_int(&q, 0);
    cnt++;
    blob_appendf(&ril, "<li>");
    if( zTitle[0] == '_' ){
      blob_appendf(&ril, "%s", zTitle);
    } else {
      blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
    }
    blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
    if( g.perm.Write && zOwner && zOwner[0] ){
      blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
    }
    if( g.perm.TktFmt ){
      blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);

    }
    if( g.perm.Admin 
     || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
    ){
      blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);

    }
    if( g.perm.TktFmt ){
      blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);

    }
    blob_appendf(&ril, "</li>\n");
  }

  Th_Store("report_items", blob_str(&ril));
  
  Th_Render(zScript);
................................................................................
      zTitle = mprintf("Copy Of %s", zTitle);
      zOwner = g.zLogin;
    }
  }
  if( zOwner==0 ) zOwner = g.zLogin;
  style_submenu_element("Cancel", "Cancel", "reportlist");
  if( rn>0 ){
    style_submenu_element("Delete", "Delete", "rptedit?rn=%d&amp;del1=1", rn);
  }
  style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
  if( zErr ){
    @ <blockquote class="reportError">%h(zErr)</blockquote>
  }
  @ <form action="rptedit" method="post"><div>
  @ <input type="hidden" name="rn" value="%d(rn)" />
................................................................................
  for(i=0; i<nArg; i++){
    char *zData;
    if( i==pState->iBg ) continue;
    zData = azArg[i];
    if( zData==0 ) zData = "";
    if( pState->iNewRow>=0 && i>=pState->iNewRow ){
      if( zTid && g.perm.Write ){
        @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
        zTid = 0;
      }
      if( zData[0] ){
        Blob content;
        @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
        blob_init(&content, zData, -1);
        wiki_convert(&content, 0, 0);
        blob_reset(&content);
      }
    }else if( azName[i][0]=='#' ){
      zTid = zData;
      if( g.perm.History ){
        @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
      }else{
        @ <td valign="top">%h(zData)</td>
      }
    }else if( zData[0]==0 ){
      @ <td valign="top">&nbsp;</td>
    }else{
      @ <td valign="top">
      @ %h(zData)
      @ </td>
    }
  }
  if( zTid && g.perm.Write ){
    @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
  }
  @ </tr>
  return 0;
}

/*
** Output the text given in the argument.  Convert tabs and newlines into
................................................................................
    return SQLITE_OK;
  }
  if( !sqlite3_stmt_readonly(pStmt) ){
    sqlite3_finalize(pStmt);
    return SQLITE_ERROR;
  }




  nCol = sqlite3_column_count(pStmt);
  azVals = fossil_malloc(2*nCol*sizeof(const char*) + 1);
  while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
    if( azCols==0 ){
      azCols = &azVals[nCol];
      for(i=0; i<nCol; i++){
        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
................................................................................

  count = 0;
  if( !tabs ){
    struct GenerateHTML sState;

    db_multi_exec("PRAGMA empty_result_callbacks=ON");
    style_submenu_element("Raw", "Raw", 
      "rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
    if( g.perm.Admin 
       || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
      style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
    }
    if( g.perm.TktFmt ){
      style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
    }







|






|
>




|
>


|
>







 







|







 







|











<
<
<
|
<









|







 







>
>
>







 







|







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
...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
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
...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
    }
    rn = db_column_int(&q, 0);
    cnt++;
    blob_appendf(&ril, "<li>");
    if( zTitle[0] == '_' ){
      blob_appendf(&ril, "%s", zTitle);
    } else {
      blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
    }
    blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
    if( g.perm.Write && zOwner && zOwner[0] ){
      blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
    }
    if( g.perm.TktFmt ){
      blob_appendf(&ril, "[%zcopy</a>] ",
                   href("%R/rptedit?rn=%d&copy=1", rn));
    }
    if( g.perm.Admin 
     || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
    ){
      blob_appendf(&ril, "[%zedit</a>]", 
                         href("%R/rptedit?rn=%d", rn));
    }
    if( g.perm.TktFmt ){
      blob_appendf(&ril, "[%zsql</a>]",
                         href("%R/rptsql?rn=%d", rn));
    }
    blob_appendf(&ril, "</li>\n");
  }

  Th_Store("report_items", blob_str(&ril));
  
  Th_Render(zScript);
................................................................................
      zTitle = mprintf("Copy Of %s", zTitle);
      zOwner = g.zLogin;
    }
  }
  if( zOwner==0 ) zOwner = g.zLogin;
  style_submenu_element("Cancel", "Cancel", "reportlist");
  if( rn>0 ){
    style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
  }
  style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
  if( zErr ){
    @ <blockquote class="reportError">%h(zErr)</blockquote>
  }
  @ <form action="rptedit" method="post"><div>
  @ <input type="hidden" name="rn" value="%d(rn)" />
................................................................................
  for(i=0; i<nArg; i++){
    char *zData;
    if( i==pState->iBg ) continue;
    zData = azArg[i];
    if( zData==0 ) zData = "";
    if( pState->iNewRow>=0 && i>=pState->iNewRow ){
      if( zTid && g.perm.Write ){
        @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
        zTid = 0;
      }
      if( zData[0] ){
        Blob content;
        @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
        blob_init(&content, zData, -1);
        wiki_convert(&content, 0, 0);
        blob_reset(&content);
      }
    }else if( azName[i][0]=='#' ){
      zTid = zData;



      @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td>

    }else if( zData[0]==0 ){
      @ <td valign="top">&nbsp;</td>
    }else{
      @ <td valign="top">
      @ %h(zData)
      @ </td>
    }
  }
  if( zTid && g.perm.Write ){
    @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
  }
  @ </tr>
  return 0;
}

/*
** Output the text given in the argument.  Convert tabs and newlines into
................................................................................
    return SQLITE_OK;
  }
  if( !sqlite3_stmt_readonly(pStmt) ){
    sqlite3_finalize(pStmt);
    return SQLITE_ERROR;
  }

  i = sqlite3_bind_parameter_index(pStmt, "$login");
  if( i ) sqlite3_bind_text(pStmt, i, g.zLogin, -1, SQLITE_TRANSIENT);

  nCol = sqlite3_column_count(pStmt);
  azVals = fossil_malloc(2*nCol*sizeof(const char*) + 1);
  while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
    if( azCols==0 ){
      azCols = &azVals[nCol];
      for(i=0; i<nCol; i++){
        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
................................................................................

  count = 0;
  if( !tabs ){
    struct GenerateHTML sState;

    db_multi_exec("PRAGMA empty_result_callbacks=ON");
    style_submenu_element("Raw", "Raw", 
      "rptview?tablist=1&%h", PD("QUERY_STRING",""));
    if( g.perm.Admin 
       || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
      style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
    }
    if( g.perm.TktFmt ){
      style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
    }

Changes to src/setup.c.

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
...
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
...
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
...
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
...
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
....
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
....
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131

1132
1133
1134
1135
1136
1137
1138
....
1312
1313
1314
1315
1316
1317
1318


































1319
1320
1321
1322
1323
1324
1325
....
1435
1436
1437
1438
1439
1440
1441



















































































































    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
    "Edit the Cascading Style Sheet used by all pages of this repository");
  setup_menu_entry("Header", "setup_header",
    "Edit HTML text inserted at the top of every page");
  setup_menu_entry("Footer", "setup_footer",
    "Edit HTML text inserted at the bottom of every page");


  setup_menu_entry("Logo", "setup_logo",
    "Change the logo and background images for the server");
  setup_menu_entry("Shunned", "shun",
    "Show artifacts that are shunned by this repository");
  setup_menu_entry("Log", "rcvfromlist",
    "A record of received artifacts and their sources");
  setup_menu_entry("User-Log", "access_log",
    "A record of login attempts");
  setup_menu_entry("Stats", "stat",
    "Display repository statistics");


  @ </table>

  style_footer();
}

/*
** WEBPAGE: setup_ulist
**
** Show a list of users.  Clicking on any user jumps to the edit
** screen for that user.
*/
void setup_ulist(void){
  Stmt s;


  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
    return;
  }

  style_submenu_element("Add", "Add User", "setup_uedit");
  style_header("User List");
  @ <table class="usetupLayoutTable">
  @ <tr><td class="usetupColumnLayout">
  @ <span class="note">Users:</span>
  @ <table class="usetupUserList">


















  @ <tr>










  @   <th class="usetupListUser" style="text-align: right;padding-right: 20px;">User&nbsp;ID</th>

  @   <th class="usetupListCap" style="text-align: center;padding-right: 15px;">Capabilities</th>

  @   <th class="usetupListCon"  style="text-align: left;">Contact&nbsp;Info</th>
  @ </tr>
  db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
  while( db_step(&s)==SQLITE_ROW ){
    const char *zCap = db_column_text(&s, 2);



    @ <tr>

    @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
    if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){
      @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
    }
    @ %h(db_column_text(&s,1))
    if( g.perm.Admin ){
      @ </a>
    }
    @ </td>
    @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
    @ <td  class="usetupListCon"  style="text-align: left;">%h(db_column_text(&s,3))</td>
    @ </tr>
................................................................................
  @   <td class="usetupEditLabel">Contact&nbsp;Info:</td>
  @   <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td>
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]

  if( g.perm.Setup ){
    @    <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />

  }
  @    <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />

  @    <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />

  @    <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />

  @    <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />

  @    <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />

  @    <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />

  @    <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br />


  @    <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />

  @    <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />

  @    <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />

  @    <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />

  @    <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />

  @    <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br />

  @    <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br />

  @    <input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments<br />


  @    <input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket<br />

  @    <input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket<br />

  @    <input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket<br />

  @    <input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket<br />

  @    <input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report<br />

  @    <input type="checkbox" name="ax"%s(oax) />%s(B('x'))Private<br />

  @    <input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip


  @   </td>
  @ </tr>
  @ <tr>
  @   <td align="right">Password:</td>
  if( zPw[0] ){
    /* Obscure the password for all users */
    @   <td><input type="password" name="pw" value="**********" /></td>
................................................................................
  @ by anonymous users.  This capability is intended for deletion of spam. 
  @ The delete capability is only in effect for 24 hours after the item
  @ is first posted.  The <span class="usertype">Setup</span> user can
  @ delete anything at any time.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">History</span> privilege allows a user
  @ to see most hyperlinks. This is recommended ON for most logged-in users
  @ but OFF for user "nobody" to avoid problems with spiders trying to walk
  @ every historical version of every baseline and file.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Zip</span> privilege allows a user to
  @ see the "download as ZIP"
  @ hyperlink and permits access to the <tt>/zip</tt> page.  This allows
  @ users to download ZIP archives without granting other rights like
  @ <span class="capability">Read</span> or
  @ <span class="capability">History</span>.  This privilege is recommended for
  @ user <span class="usertype">nobody</span> so that automatic package
  @ downloaders can obtain the sources without going through the login
  @ procedure.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Check-in</span> privilege allows remote
  @ users to "push". The <span class="capability">Check-out</span> privilege
................................................................................
  @ capabilities of the <span class="usertype">nobody</span> user are
  @ inherited by all users, regardless of whether or not they are logged in.
  @ To disable universal access to the repository, make sure no user named 
  @ <span class="usertype">nobody</span> exists or that the
  @ <span class="usertype">nobody</span> user has no capabilities
  @ enabled. The password for <span class="usertype">nobody</span> is ignore.
  @ To avoid problems with spiders overloading the server, it is recommended
  @ that the <span class="capability">h</span> (History) capability be turned 
  @ off for the <span class="usertype">nobody</span> user.
  @ </p></li>
  @
  @ <li><p>
  @ Login is required for user <span class="usertype">anonymous</span> but the
  @ password is displayed on the login screen beside the password entry box
  @ so anybody who can read should be able to login as anonymous.
  @ On the other hand, spiders and web-crawlers will typically not
................................................................................
  @ <p>Fossil tries to limit out-bound sync, clone, and pull packets
  @ to this many bytes, uncompressed.  If the client requires more data
  @ than this, then the client will issue multiple HTTP requests.
  @ Values below 1 million are not recommended.  5 million is a
  @ reasonable number.</p>

  @ <hr />

  onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent",
                  "auto-enable-hyperlinks", "autohyperlink", 1);
  @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
  @ including user "nobody", as long as the User-Agent string in the HTTP header
  @ indicates that the request is coming from an actual human being and not a


  @ a robot or script.  Note:  Bots can specify whatever User-Agent string they
  @ that want.  So a bot that wants to impersonate a human can easily do so.
  @ Hence, this technique does not necessarily exclude malicious bots.


















  @ </p>


  @ <hr />
  onoff_attribute("Allow users to register themselves",
                  "self-register", "selfregister", 0);
  @ <p>Allow users to register themselves through the HTTP UI. 
  @ The registration form always requires filling in a CAPTCHA 
  @ (<em>auto-captcha</em> setting is ignored). Still, bear in mind that anyone
................................................................................
  @ can register under any user name. This option is useful for public projects
  @ where you do not want everyone in any ticket discussion to be named 
  @ "Anonymous".</p>

  @ <hr />
  entry_attribute("Default privileges", 10, "default-perms",
                  "defaultperms", "u");
  @ <p>Permissions given to users that register themselves using the HTTP UI
  @ or are registered by the administrator using the command line interface.


  @ </p>

  @ <hr />
  onoff_attribute("Show javascript button to fill in CAPTCHA",
                  "auto-captcha", "autocaptcha", 0);
  @ <p>When enabled, a button appears on the login screen for user
  @ "anonymous" that will automatically fill in the CAPTCHA password.
................................................................................
      if( pSet->versionable ){
        @  (v)<br />
      } else {
        @ <br />
      }
    }
  }
  @ </td><td style="width: 30;"></td><td valign="top">
  for(pSet=ctrlSettings; pSet->name!=0; pSet++){
    if( pSet->width!=0 ){
      entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name,
                      pSet->var!=0 ? pSet->var : pSet->name,
                      (char*)pSet->def);
      if( pSet->versionable ){
        @  (v)<br />
................................................................................
        @ <br />
      }
    }
  }
  @ </td></tr></table>
  @ <p><input type="submit"  name="submit" value="Apply Changes" /></p>
  @ </div></form>
  @ <p>Settings marked with (v) are 'versionable' and will be overridden by the contents of files named <tt>.fossil-settings/PROPERTY</tt>.</p>

  @ <hr /><p>
  @ These settings work in the same way, as the <kbd>set</kbd> commandline:<br />

  @ </p><pre>%s(zHelp_setting_cmd)</pre>
  db_end_transaction(0);
  style_footer();
}

/*
** WEBPAGE: setup_config
................................................................................
  @ <a href="setup_header">header</a> editing screens.
  @ <blockquote><pre>
  @ %h(zDefaultFooter)
  @ </pre></blockquote>
  style_footer();
  db_end_transaction(0);
}



































/*
** WEBPAGE: setup_logo
*/
void setup_logo(void){
  const char *zLogoMime = db_get("logo-mimetype","image/gif");
  const char *aLogoImg = P("logoim");
................................................................................
  @
  @ <p><span class="note">Note:</span>  Your browser has probably cached these
  @ images, so you may need to press the Reload button before changes will
  @ take effect. </p>
  style_footer();
  db_end_transaction(0);
}


























































































































>
>










>
>













>













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

>
|



|







 







>

|
>

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







 







|


|








|
|







 







|
|







 







>
|
|

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

>







 







|
|
>
>







 







|







 







|
>

|
>







 







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







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
...
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
...
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
...
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
...
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
....
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
....
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
....
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
....
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
    "Select from a menu of prepackaged \"skins\" for the web interface");
  setup_menu_entry("CSS", "setup_editcss",
    "Edit the Cascading Style Sheet used by all pages of this repository");
  setup_menu_entry("Header", "setup_header",
    "Edit HTML text inserted at the top of every page");
  setup_menu_entry("Footer", "setup_footer",
    "Edit HTML text inserted at the bottom of every page");
  setup_menu_entry("Ad-Unit", "setup_adunit",
    "Edit HTML text for an ad unit inserted after the menu bar");
  setup_menu_entry("Logo", "setup_logo",
    "Change the logo and background images for the server");
  setup_menu_entry("Shunned", "shun",
    "Show artifacts that are shunned by this repository");
  setup_menu_entry("Log", "rcvfromlist",
    "A record of received artifacts and their sources");
  setup_menu_entry("User-Log", "access_log",
    "A record of login attempts");
  setup_menu_entry("Stats", "stat",
    "Display repository statistics");
  setup_menu_entry("SQL", "admin_sql",
    "Enter raw SQL commands");
  @ </table>

  style_footer();
}

/*
** WEBPAGE: setup_ulist
**
** Show a list of users.  Clicking on any user jumps to the edit
** screen for that user.
*/
void setup_ulist(void){
  Stmt s;
  int prevLevel = 0;

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed();
    return;
  }

  style_submenu_element("Add", "Add User", "setup_uedit");
  style_header("User List");
  @ <table class="usetupLayoutTable">
  @ <tr><td class="usetupColumnLayout">
  @ <span class="note">Users:</span>
  @ <table class="usetupUserList">
  prevLevel = 0;
  db_prepare(&s, 
     "SELECT uid, login, cap, info, 1 FROM user"
     " WHERE login IN ('anonymous','nobody','developer','reader') "
     " UNION ALL "
     "SELECT uid, login, cap, info, 2 FROM user"
     " WHERE login NOT IN ('anonymous','nobody','developer','reader') "
     "ORDER BY 5, 2"
  );
  while( db_step(&s)==SQLITE_ROW ){
    int iLevel = db_column_int(&s, 4);
    const char *zCap = db_column_text(&s, 2);
    const char *zLogin = db_column_text(&s, 1);
    if( iLevel>prevLevel ){
      if( prevLevel>0 ){
        @ <tr><td colspan="3"><hr></td></tr>
      }
      if( iLevel==1 ){
        @ <tr>
        @   <th class="usetupListUser"
        @    style="text-align: right;padding-right: 20px;">Category</th>
        @   <th class="usetupListCap"
        @    style="text-align: center;padding-right: 15px;">Capabilities</th>
        @   <th class="usetupListCon"
        @    style="text-align: left;">Notes</th>
        @ </tr>
      }else{
        @ <tr>
        @   <th class="usetupListUser"
        @    style="text-align: right;padding-right: 20px;">User&nbsp;ID</th>
        @   <th class="usetupListCap"
        @    style="text-align: center;padding-right: 15px;">Capabilities</th>
        @   <th class="usetupListCon"
        @    style="text-align: left;">Contact&nbsp;Info</th>
        @ </tr>



      }
      prevLevel = iLevel;
    }
    @ <tr>
    @ <td class="usetupListUser"
    @     style="text-align: right;padding-right: 20px;white-space:nowrap;">
    if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){
      @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
    }
    @ %h(zLogin)
    if( g.perm.Admin ){
      @ </a>
    }
    @ </td>
    @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
    @ <td  class="usetupListCon"  style="text-align: left;">%h(db_column_text(&s,3))</td>
    @ </tr>
................................................................................
  @   <td class="usetupEditLabel">Contact&nbsp;Info:</td>
  @   <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td>
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]
  @ <table border=0><tr><td valign="top">
  if( g.perm.Setup ){
    @  <label><input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup
    @  </label><br />
  }
  @  <label><input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin
  @  </label><br />
  @  <label><input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete
  @  </label><br />
  @  <label><input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email
  @  </label><br />
  @  <label><input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password
  @  </label><br />
  @  <label><input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In
  @  </label><br />
  @  <label><input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out
  @  </label><br />
  @  <label><input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks
  @  </label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader
  @  </label><br />
  @  <label><input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer
  @  </label><br />
  @  <label><input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone
  @  </label><br />
  @  <label><input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki
  @  </label><br />
  @  <label><input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments
  @  </label><br />
  @ </td><td><td width="40"></td><td valign="top">
  @  <label><input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket
  @  </label><br />
  @  <label><input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket
  @  </label><br />
  @  <label><input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket
  @  </label><br />
  @  <label><input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket
  @  </label><br />
  @  <label><input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report
  @  </label><br />
  @  <label><input type="checkbox" name="ax"%s(oax) />%s(B('x'))Private
  @  </label><br />
  @  <label><input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip
  @  </label>
  @ </td></tr></table>
  @   </td>
  @ </tr>
  @ <tr>
  @   <td align="right">Password:</td>
  if( zPw[0] ){
    /* Obscure the password for all users */
    @   <td><input type="password" name="pw" value="**********" /></td>
................................................................................
  @ by anonymous users.  This capability is intended for deletion of spam. 
  @ The delete capability is only in effect for 24 hours after the item
  @ is first posted.  The <span class="usertype">Setup</span> user can
  @ delete anything at any time.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Hyperlinks</span> privilege allows a user
  @ to see most hyperlinks. This is recommended ON for most logged-in users
  @ but OFF for user "nobody" to avoid problems with spiders trying to walk
  @ every diff and annotation of every historical check-in and file.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Zip</span> privilege allows a user to
  @ see the "download as ZIP"
  @ hyperlink and permits access to the <tt>/zip</tt> page.  This allows
  @ users to download ZIP archives without granting other rights like
  @ <span class="capability">Read</span> or
  @ <span class="capability">Hyperlink</span>.  The "z" privilege is recommended
  @ for user <span class="usertype">nobody</span> so that automatic package
  @ downloaders can obtain the sources without going through the login
  @ procedure.
  @ </p></li>
  @
  @ <li><p>
  @ The <span class="capability">Check-in</span> privilege allows remote
  @ users to "push". The <span class="capability">Check-out</span> privilege
................................................................................
  @ capabilities of the <span class="usertype">nobody</span> user are
  @ inherited by all users, regardless of whether or not they are logged in.
  @ To disable universal access to the repository, make sure no user named 
  @ <span class="usertype">nobody</span> exists or that the
  @ <span class="usertype">nobody</span> user has no capabilities
  @ enabled. The password for <span class="usertype">nobody</span> is ignore.
  @ To avoid problems with spiders overloading the server, it is recommended
  @ that the <span class="capability">h</span> (Hyperlinks) capability be
  @ turned off for the <span class="usertype">nobody</span> user.
  @ </p></li>
  @
  @ <li><p>
  @ Login is required for user <span class="usertype">anonymous</span> but the
  @ password is displayed on the login screen beside the password entry box
  @ so anybody who can read should be able to login as anonymous.
  @ On the other hand, spiders and web-crawlers will typically not
................................................................................
  @ <p>Fossil tries to limit out-bound sync, clone, and pull packets
  @ to this many bytes, uncompressed.  If the client requires more data
  @ than this, then the client will issue multiple HTTP requests.
  @ Values below 1 million are not recommended.  5 million is a
  @ reasonable number.</p>

  @ <hr />
  onoff_attribute(
      "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
      "auto-hyperlink", "autohyperlink", 1);
  @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
  @ including user "nobody", as long as (1) the User-Agent string in the
  @ HTTP header indicates that the request is coming from an actual human
  @ being and not a a robot or spider and (2) the user agent is able to
  @ run Javascript in order to set the href= attribute of hyperlinks.  Bots
  @ and spiders can specify whatever User-Agent string they that want and


  @ they can run javascript just like browsers.  But most bots don't go to
  @ that much trouble so this is normally an effective defense.</p>
  @
  @ <p>You do not normally want a bot to walk your entire repository because
  @ if it does, your server will end up computing diffs and annotations for
  @ every historical version of every file and creating ZIPs and tarballs of
  @ every historical check-in, which can use a lot of CPU and bandwidth
  @ even for relatively small projects.</p>

  @ <hr />
  entry_attribute("Public pages", 30, "public-pages",
                  "pubpage", "");
  @ <p>A comma-separated list of glob patterns for pages that are accessible
  @ without needing a login and using the privileges given by the
  @ "Default privileges" setting below.  Example use case: Set this field
  @ to "/doc/trunk/www/*" to give anonymous users read-only permission to the 
  @ latest version of the embedded documentation in the www/ folder without
  @ allowing them to see the rest of the source code.
  @ </p>


  @ <hr />
  onoff_attribute("Allow users to register themselves",
                  "self-register", "selfregister", 0);
  @ <p>Allow users to register themselves through the HTTP UI. 
  @ The registration form always requires filling in a CAPTCHA 
  @ (<em>auto-captcha</em> setting is ignored). Still, bear in mind that anyone
................................................................................
  @ can register under any user name. This option is useful for public projects
  @ where you do not want everyone in any ticket discussion to be named 
  @ "Anonymous".</p>

  @ <hr />
  entry_attribute("Default privileges", 10, "default-perms",
                  "defaultperms", "u");
  @ <p>Permissions given to users that... <ul><li>register themselves using
  @ the self-registration procedure (if enabled), or <li>access "public"
  @ pages identified by the public-pages glob pattern above, or <li>
  @ are users newly created by the administrator.</ul>
  @ </p>

  @ <hr />
  onoff_attribute("Show javascript button to fill in CAPTCHA",
                  "auto-captcha", "autocaptcha", 0);
  @ <p>When enabled, a button appears on the login screen for user
  @ "anonymous" that will automatically fill in the CAPTCHA password.
................................................................................
      if( pSet->versionable ){
        @  (v)<br />
      } else {
        @ <br />
      }
    }
  }
  @ </td><td style="width:50px;"></td><td valign="top">
  for(pSet=ctrlSettings; pSet->name!=0; pSet++){
    if( pSet->width!=0 ){
      entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name,
                      pSet->var!=0 ? pSet->var : pSet->name,
                      (char*)pSet->def);
      if( pSet->versionable ){
        @  (v)<br />
................................................................................
        @ <br />
      }
    }
  }
  @ </td></tr></table>
  @ <p><input type="submit"  name="submit" value="Apply Changes" /></p>
  @ </div></form>
  @ <p>Settings marked with (v) are 'versionable' and will be overridden
  @ by the contents of files named <tt>.fossil-settings/PROPERTY</tt>.</p>
  @ <hr /><p>
  @ These settings work in the same way, as the <kbd>set</kbd>
  @ commandline:<br />
  @ </p><pre>%s(zHelp_setting_cmd)</pre>
  db_end_transaction(0);
  style_footer();
}

/*
** WEBPAGE: setup_config
................................................................................
  @ <a href="setup_header">header</a> editing screens.
  @ <blockquote><pre>
  @ %h(zDefaultFooter)
  @ </pre></blockquote>
  style_footer();
  db_end_transaction(0);
}

/*
** WEBPAGE: setup_adunit
*/
void setup_adunit(void){
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  db_begin_transaction();
  if( P("clear")!=0 ){
    db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
  }else{
    textarea_attribute(0, 0, 0, "adunit", "adunit", "");
  }
  style_header("Edit Ad Unit");
  @ <form action="%s(g.zTop)/setup_adunit" method="post"><div>
  login_insert_csrf_secret();
  @ <p>Edit HTML text for an ad unit that will be inserted after the
  @ menu bar and above the content of every page.</p>
  textarea_attribute("", 20, 80, "adunit", "adunit", "");
  @ <br />
  onoff_attribute("Omit ads to administrator",
     "adunit-omit-if-admin", "oia", 0);
  @ <br />
  onoff_attribute("Omit ads to logged-in users",
     "adunit-omit-if-user", "oiu", 0);
  @ <br />
  @ <input type="submit" name="submit" value="Apply Changes" />
  @ <input type="submit" name="clear" value="Delete Ad-Unit" />
  @ </div></form>
  style_footer();
  db_end_transaction(0);
}

/*
** WEBPAGE: setup_logo
*/
void setup_logo(void){
  const char *zLogoMime = db_get("logo-mimetype","image/gif");
  const char *aLogoImg = P("logoim");
................................................................................
  @
  @ <p><span class="note">Note:</span>  Your browser has probably cached these
  @ images, so you may need to press the Reload button before changes will
  @ take effect. </p>
  style_footer();
  db_end_transaction(0);
}


/*
** WEBPAGE: admin_sql
**
** Run raw SQL commands against the database file using the web interface.
*/
void sql_page(void){
  const char *zQ = P("q");
  int go = P("go")!=0;
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  db_begin_transaction();
  style_header("Raw SQL Commands");
  @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
  @ run by this page.  You can do serious and irrepairable damage to the
  @ repository.  Proceed with extreme caution.</p>
  @
  @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
  if( g.configOpen ){
    @ <li>config &rarr; %s(db_name("configdb"))
  }
  if( g.localOpen ){
    @ <li>local-checkout &rarr; %s(db_name("localdb"))
  }
  @ </ul></p>
  @
  @ <form method="post" action="%s(g.zTop)/admin_sql">
  login_insert_csrf_secret();
  @ SQL:<br />
  @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br />
  @ <input type="submit" name="go" value="Run SQL">
  @ <input type="submit" name="schema" value="Show Schema">
  @ <input type="submit" name="tablelist" value="List Tables">
  @ </form>
  if( P("schema") ){
    zQ = sqlite3_mprintf(
            "SELECT sql FROM %s.sqlite_master WHERE sql IS NOT NULL",
            db_name("repository"));
    go = 1;
  }else if( P("tablelist") ){
    zQ = sqlite3_mprintf(
            "SELECT name FROM %s.sqlite_master WHERE type='table'"
            " ORDER BY name",
            db_name("repository"));
    go = 1;
  }
  if( go ){
    sqlite3_stmt *pStmt;
    int rc;
    const char *zTail;
    int nCol;
    int nRow = 0;
    int i;
    @ <hr />
    login_verify_csrf_secret();
    rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
    if( rc!=SQLITE_OK ){
      @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
      sqlite3_finalize(pStmt);
    }else if( pStmt==0 ){
      /* No-op */
    }else if( (nCol = sqlite3_column_count(pStmt))==0 ){
      sqlite3_step(pStmt);
      rc = sqlite3_finalize(pStmt);
      if( rc ){
        @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
      }
    }else{
      @ <table border=1>
      while( sqlite3_step(pStmt)==SQLITE_ROW ){
        if( nRow==0 ){
          @ <tr>
          for(i=0; i<nCol; i++){
            @ <th>%h(sqlite3_column_name(pStmt, i))</th>
          }
          @ </tr>
        }
        nRow++;
        @ <tr>
        for(i=0; i<nCol; i++){
          switch( sqlite3_column_type(pStmt, i) ){
            case SQLITE_INTEGER:
            case SQLITE_FLOAT: {
               @ <td align="right" valign="top">
               @ %s(sqlite3_column_text(pStmt, i))</td>
               break;
            }
            case SQLITE_NULL: {
               @ <td valign="top" align="center"><i>NULL</i></td>
               break;
            }
            case SQLITE_TEXT: {
               const char *zText = (const char*)sqlite3_column_text(pStmt, i);
               @ <td align="left" valign="top"
               @ style="white-space:pre;">%h(zText)</td>
               break;
            }
            case SQLITE_BLOB: {
               @ <td valign="top" align="center">
               @ <i>%d(sqlite3_column_bytes(pStmt, i))-byte BLOB</i></td>
               break;
            }
          }
        }
        @ </tr>
      }
      sqlite3_finalize(pStmt);
      @ </table>
    }
  }
  style_footer();
}

Changes to src/shell.c.

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
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
....
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192

2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203

2204
2205
2206
2207
2208
2209
2210
....
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285


























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
....
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
....
2568
2569
2570
2571
2572
2573
2574
2575


2576
2577
2578
2579
2580
2581
2582
....
2661
2662
2663
2664
2665
2666
2667
2668

2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
....
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
#include <ctype.h>
#include <stdarg.h>

#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__)
# include <signal.h>
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>
# endif
# include <unistd.h>
# include <sys/types.h>
#endif

#ifdef __OS2__
# include <unistd.h>
#endif

#ifdef HAVE_EDITLINE
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#endif
................................................................................
static int enableTimer = 0;

/* ctype macros that work with signed characters */
#define IsSpace(X)  isspace((unsigned char)X)
#define IsDigit(X)  isdigit((unsigned char)X)
#define ToLower(X)  (char)tolower((unsigned char)X)

#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
#include <sys/time.h>
#include <sys/resource.h>

/* Saved resource information for the beginning of an operation */
static struct rusage sBegin;

/*
................................................................................
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
  char *zBlob = (char *)pBlob;
  fprintf(out,"X'");
  for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]); }
  fprintf(out,"'");
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
*/
static void output_quoted_string(FILE *out, const char *z){
................................................................................
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
        rc = SQLITE_OK;
      }else{
        zShellStatic = azArg[1];
        rc = sqlite3_exec(p->db,
          "SELECT sql FROM "
          "  (SELECT sql sql, type type, tbl_name tbl_name, name name"
          "     FROM sqlite_master UNION ALL"
          "   SELECT sql, type, tbl_name, name FROM sqlite_temp_master) "
          "WHERE lower(tbl_name) LIKE shellstatic()"
          "  AND type!='meta' AND sql NOTNULL "
          "ORDER BY substr(type,2,1), name",

          callback, &data, &zErrMsg);
        zShellStatic = 0;
      }
    }else{
      rc = sqlite3_exec(p->db,
         "SELECT sql FROM "
         "  (SELECT sql sql, type type, tbl_name tbl_name, name name"
         "     FROM sqlite_master UNION ALL"
         "   SELECT sql, type, tbl_name, name FROM sqlite_temp_master) "
         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
         "ORDER BY substr(type,2,1), name",

         callback, &data, &zErrMsg
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
................................................................................
  }else

  if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
    p->statsOn = booleanValue(azArg[1]);
  }else

  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
    char **azResult;
    int nRow;
    char *zErrMsg;
    open_db(p);
    if( nArg==1 ){
      rc = sqlite3_get_table(p->db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg
      );
    }else{
      zShellStatic = azArg[1];
      rc = sqlite3_get_table(p->db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name LIKE shellstatic() "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') AND name LIKE shellstatic() "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg
      );
      zShellStatic = 0;
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
    }else if( rc != SQLITE_OK ){
      fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n");
      rc = 1;
    }else{


























      int len, maxlen = 0;
      int i, j;
      int nPrintCol, nPrintRow;
      for(i=1; i<=nRow; i++){
        if( azResult[i]==0 ) continue;
        len = strlen30(azResult[i]);
        if( len>maxlen ) maxlen = len;
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i+1; j<=nRow; j+=nPrintRow){
          char *zSp = j<=nPrintRow ? "" : "  ";
          printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
        }
        printf("\n");
      }
    }

    sqlite3_free_table(azResult);
  }else

  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
    } aCtrl[] = {
................................................................................
  if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
   && nArg==2
  ){
    enableTimer = booleanValue(azArg[1]);
  }else
  
  if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){

    output_file_close(p->traceOut);
    p->traceOut = output_file_open(azArg[1]);
#ifndef SQLITE_OMIT_TRACE
    if( p->traceOut==0 ){
      sqlite3_trace(p->db, 0, 0);
    }else{
      sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
................................................................................
  int startline = 0;

  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
    fflush(p->out);
    free(zLine);
    zLine = one_input_line(zSql, in);
    if( zLine==0 ){
      break;  /* We have reached EOF */


    }
    if( seenInterrupt ){
      if( in!=0 ) break;
      seenInterrupt = 0;
    }
    lineno++;
    if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
................................................................................
** Return a pathname which is the user's home directory.  A
** 0 return indicates an error of some kind.
*/
static char *find_home_dir(void){
  static char *home_dir = NULL;
  if( home_dir ) return home_dir;

#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)

  struct passwd *pwent;
  uid_t uid = getuid();
  if( (pwent=getpwuid(uid)) != NULL) {
    home_dir = pwent->pw_dir;

  }
#endif

#if defined(_WIN32_WCE)
  /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
   */
  home_dir = "/";
#else

#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
  if (!home_dir) {
    home_dir = getenv("USERPROFILE");
  }
#endif

  if (!home_dir) {
    home_dir = getenv("HOME");
  }

#if defined(_WIN32) || defined(WIN32) || defined(__OS2__)
  if (!home_dir) {
    char *zDrive, *zPath;
    int n;
    zDrive = getenv("HOMEDRIVE");
    zPath = getenv("HOMEPATH");
    if( zDrive && zPath ){
      n = strlen30(zDrive) + strlen30(zPath) + 1;
................................................................................
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
      }
    }
  }
  if( i<argc ){
#if defined(SQLITE_OS_OS2) && SQLITE_OS_OS2
    data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] );
#else
    data.zDbFilename = argv[i++];
#endif
  }else{
#ifndef SQLITE_OMIT_MEMORYDB
    data.zDbFilename = ":memory:";
#else
    data.zDbFilename = 0;
#endif
    /***** Begin Fossil Patch *****/







|








<
<
<
<







 







|







 







|







 







|

|


|
>






|

|

|
>







 







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



|
<







|
|





>
|







 







>







 







|
>
>







 







|
>
|
|
|
|
>









|









|







 







<
<
<

<







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47




48
49
50
51
52
53
54
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
....
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
....
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
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
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
....
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
....
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
....
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
....
2930
2931
2932
2933
2934
2935
2936



2937

2938
2939
2940
2941
2942
2943
2944
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "sqlite3.h"
#include <ctype.h>
#include <stdarg.h>

#if !defined(_WIN32) && !defined(WIN32)
# include <signal.h>
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>
# endif
# include <unistd.h>
# include <sys/types.h>
#endif





#ifdef HAVE_EDITLINE
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
# include <readline/readline.h>
# include <readline/history.h>
#endif
................................................................................
static int enableTimer = 0;

/* ctype macros that work with signed characters */
#define IsSpace(X)  isspace((unsigned char)X)
#define IsDigit(X)  isdigit((unsigned char)X)
#define ToLower(X)  (char)tolower((unsigned char)X)

#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL)
#include <sys/time.h>
#include <sys/resource.h>

/* Saved resource information for the beginning of an operation */
static struct rusage sBegin;

/*
................................................................................
/*
** Output the given string as a hex-encoded blob (eg. X'1234' )
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
  char *zBlob = (char *)pBlob;
  fprintf(out,"X'");
  for(i=0; i<nBlob; i++){ fprintf(out,"%02x",zBlob[i]&0xff); }
  fprintf(out,"'");
}

/*
** Output the given string as a quoted string using SQL quoting conventions.
*/
static void output_quoted_string(FILE *out, const char *z){
................................................................................
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
        rc = SQLITE_OK;
      }else{
        zShellStatic = azArg[1];
        rc = sqlite3_exec(p->db,
          "SELECT sql FROM "
          "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
          "     FROM sqlite_master UNION ALL"
          "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
          "WHERE lower(tbl_name) LIKE shellstatic()"
          "  AND type!='meta' AND sql NOTNULL "
          "ORDER BY substr(type,2,1), "
                  " CASE type WHEN 'view' THEN rowid ELSE name END",
          callback, &data, &zErrMsg);
        zShellStatic = 0;
      }
    }else{
      rc = sqlite3_exec(p->db,
         "SELECT sql FROM "
         "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
         "     FROM sqlite_master UNION ALL"
         "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'"
         "ORDER BY substr(type,2,1),"
                  " CASE type WHEN 'view' THEN rowid ELSE name END",
         callback, &data, &zErrMsg
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
      rc = 1;
................................................................................
  }else

  if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
    p->statsOn = booleanValue(azArg[1]);
  }else

  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
    sqlite3_stmt *pStmt;
    char **azResult;
    int nRow, nAlloc;
    char *zSql = 0;
    int ii;
    open_db(p);
    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ) return rc;
    zSql = sqlite3_mprintf(
        "SELECT name FROM sqlite_master"
        " WHERE type IN ('table','view')"
        "   AND name NOT LIKE 'sqlite_%%'"
        "   AND name LIKE ?1");
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
      const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
      if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;
      if( strcmp(zDbName,"temp")==0 ){
        zSql = sqlite3_mprintf(
                 "%z UNION ALL "
                 "SELECT 'temp.' || name FROM sqlite_temp_master"
                 " WHERE type IN ('table','view')"
                 "   AND name NOT LIKE 'sqlite_%%'"
                 "   AND name LIKE ?1", zSql);
      }else{
        zSql = sqlite3_mprintf(
                 "%z UNION ALL "
                 "SELECT '%q.' || name FROM \"%w\".sqlite_master"
                 " WHERE type IN ('table','view')"
                 "   AND name NOT LIKE 'sqlite_%%'"
                 "   AND name LIKE ?1", zSql, zDbName, zDbName);
      }
    }
    sqlite3_finalize(pStmt);
    zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ) return rc;
    nRow = nAlloc = 0;
    azResult = 0;
    if( nArg>1 ){
      sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
    }else{
      sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
    }
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
      if( nRow>=nAlloc ){
        char **azNew;
        int n = nAlloc*2 + 10;
        azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
        if( azNew==0 ){
          fprintf(stderr, "Error: out of memory\n");
          break;
        }
        nAlloc = n;
        azResult = azNew;
      }
      azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
      if( azResult[nRow] ) nRow++;
    }
    sqlite3_finalize(pStmt);        
    if( nRow>0 ){
      int len, maxlen = 0;
      int i, j;
      int nPrintCol, nPrintRow;
      for(i=0; i<nRow; i++){

        len = strlen30(azResult[i]);
        if( len>maxlen ) maxlen = len;
      }
      nPrintCol = 80/(maxlen+2);
      if( nPrintCol<1 ) nPrintCol = 1;
      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
      for(i=0; i<nPrintRow; i++){
        for(j=i; j<nRow; j+=nPrintRow){
          char *zSp = j<nPrintRow ? "" : "  ";
          printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : "");
        }
        printf("\n");
      }
    }
    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
    sqlite3_free(azResult);
  }else

  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
    } aCtrl[] = {
................................................................................
  if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0
   && nArg==2
  ){
    enableTimer = booleanValue(azArg[1]);
  }else
  
  if( c=='t' && strncmp(azArg[0], "trace", n)==0 && nArg>1 ){
    open_db(p);
    output_file_close(p->traceOut);
    p->traceOut = output_file_open(azArg[1]);
#ifndef SQLITE_OMIT_TRACE
    if( p->traceOut==0 ){
      sqlite3_trace(p->db, 0, 0);
    }else{
      sqlite3_trace(p->db, sql_trace_callback, p->traceOut);
................................................................................
  int startline = 0;

  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
    fflush(p->out);
    free(zLine);
    zLine = one_input_line(zSql, in);
    if( zLine==0 ){
      /* End of input */
      if( stdin_is_interactive ) printf("\n");
      break;
    }
    if( seenInterrupt ){
      if( in!=0 ) break;
      seenInterrupt = 0;
    }
    lineno++;
    if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue;
................................................................................
** Return a pathname which is the user's home directory.  A
** 0 return indicates an error of some kind.
*/
static char *find_home_dir(void){
  static char *home_dir = NULL;
  if( home_dir ) return home_dir;

#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL)
  {
    struct passwd *pwent;
    uid_t uid = getuid();
    if( (pwent=getpwuid(uid)) != NULL) {
      home_dir = pwent->pw_dir;
    }
  }
#endif

#if defined(_WIN32_WCE)
  /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
   */
  home_dir = "/";
#else

#if defined(_WIN32) || defined(WIN32)
  if (!home_dir) {
    home_dir = getenv("USERPROFILE");
  }
#endif

  if (!home_dir) {
    home_dir = getenv("HOME");
  }

#if defined(_WIN32) || defined(WIN32)
  if (!home_dir) {
    char *zDrive, *zPath;
    int n;
    zDrive = getenv("HOMEDRIVE");
    zPath = getenv("HOMEPATH");
    if( zDrive && zPath ){
      n = strlen30(zDrive) + strlen30(zPath) + 1;
................................................................................
      }else{
        fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]);
        exit(1);
      }
    }
  }
  if( i<argc ){



    data.zDbFilename = argv[i++];

  }else{
#ifndef SQLITE_OMIT_MEMORYDB
    data.zDbFilename = ":memory:";
#else
    data.zDbFilename = 0;
#endif
    /***** Begin Fossil Patch *****/

Changes to src/sqlite3.c.

1
2
3
4
5
6
7
8
9
10
...
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
...
439
440
441
442
443
444
445
446



447
448


449
450
451
452
453



454
455
456
457
458
459
460
...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
...
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
...
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
....
1004
1005
1006
1007
1008
1009
1010

1011
1012
1013
1014
1015
1016
1017
....
1023
1024
1025
1026
1027
1028
1029

1030
1031
1032
1033
1034
1035
1036
....
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
....
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
....
3120
3121
3122
3123
3124
3125
3126
3127
3128

3129
3130
3131
3132
3133
3134
3135

3136
3137
3138

3139
3140
3141
3142
3143
3144
3145
....
4994
4995
4996
4997
4998
4999
5000





































5001
5002
5003
5004
5005
5006
5007
....
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
....
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
....
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
....
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
....
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
....
9336
9337
9338
9339
9340
9341
9342
















9343
9344
9345
9346
9347
9348
9349
....
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
....
9891
9892
9893
9894
9895
9896
9897

9898
9899
9900
9901
9902
9903
9904
.....
10930
10931
10932
10933
10934
10935
10936


10937
10938
10939
10940
10941
10942
10943
10944
10945








10946
10947
10948
10949
10950
10951
10952
.....
11620
11621
11622
11623
11624
11625
11626

11627

11628
11629
11630
11631
11632
11633
11634
.....
11744
11745
11746
11747
11748
11749
11750

11751
11752
11753
11754
11755
11756
11757
.....
12025
12026
12027
12028
12029
12030
12031

12032
12033
12034
12035
12036
12037
12038
.....
12478
12479
12480
12481
12482
12483
12484



12485
12486
12487
12488
12489
12490
12491
.....
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
17664
17665
17666
17667
17668
17669
17670
17671
17672
17673
17674
17675
17676
17677
17678
17679
17680
17681
17682
17683
17684
17685
17686
17687
17688
17689
17690
17691
17692
17693
17694
17695
17696
17697
17698
17699
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710
17711
17712
17713
17714
17715
17716
17717
17718
17719
17720
17721
17722
17723
17724
17725
17726
17727
17728
17729
17730
17731
17732
17733
17734
17735
17736
17737
17738
17739
17740
17741
17742
17743
17744
17745
17746
17747
17748
17749
17750
17751
17752
17753
17754
17755
17756
17757
17758
17759
17760
17761
17762
17763
17764
17765
17766
17767
17768
17769
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796
17797
17798
17799
17800
17801
17802
17803
17804
17805
17806
17807
17808
17809
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820
17821
17822
17823
17824
17825
17826
17827
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860
17861
17862
17863
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
17923
17924
17925
17926
17927
17928
17929
17930
17931
17932
17933
17934
.....
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344
18345
18346
.....
18385
18386
18387
18388
18389
18390
18391


18392
18393
18394
18395
18396



18397

18398
18399
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
.....
18470
18471
18472
18473
18474
18475
18476



18477

18478
18479
18480
18481
18482
18483
18484
.....
19101
19102
19103
19104
19105
19106
19107




19108
19109
19110
19111
19112
19113
19114
.....
19514
19515
19516
19517
19518
19519
19520
19521

19522
19523
19524
19525
19526
19527
19528
.....
19818
19819
19820
19821
19822
19823
19824
19825
19826
19827



19828
19829
19830
19831
19832
19833
19834
.....
19853
19854
19855
19856
19857
19858
19859
19860
19861
19862
19863
19864
19865
19866
19867
.....
19868
19869
19870
19871
19872
19873
19874
19875
19876
19877
19878
19879
19880
19881
19882
.....
21441
21442
21443
21444
21445
21446
21447
21448
21449
21450
21451
21452
21453
21454
21455
.....
22696
22697
22698
22699
22700
22701
22702
22703
22704
22705
22706
22707
22708
22709
22710
22711
22712
22713
22714
22715
22716
22717
22718
22719
22720
22721
22722
22723
22724
22725
22726
22727
22728
22729
22730
22731
22732
22733
22734
22735
22736
22737
22738
22739
22740
22741
22742
22743
22744
22745
22746
22747
22748
22749
22750
22751
22752
22753
22754
22755
22756
22757
22758
22759
22760
22761
22762
22763
22764
22765
22766
22767
22768
22769
22770
22771
22772
22773
22774
22775
22776
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786
22787
22788
22789
22790
22791
22792
22793
22794
22795
22796
22797
22798
22799
22800
22801
22802
22803
22804
22805
22806
22807
22808
22809
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22829
22830
22831
22832
22833
22834
22835
22836
22837
22838
22839
22840
22841
22842
22843
22844
22845
22846
22847
22848
22849
22850
22851
22852
22853
22854
22855
22856
22857
22858
22859
22860
22861
22862
22863
22864
22865
22866
22867
22868
22869
22870
22871
22872
22873
22874
22875
22876
22877
22878
22879
22880
22881
22882
22883
22884
22885
22886
22887
22888
22889
22890
22891
22892
22893
22894
22895
22896
22897
22898
22899
22900
22901
22902
22903
22904
22905
22906
22907
22908
22909
22910
22911
22912
22913
22914
22915
22916
22917
22918
22919
22920
22921
22922
22923
22924
22925
22926
22927
22928
22929
22930
22931
22932
22933
22934
22935
22936
22937
22938
22939
22940
22941
22942
22943
22944
22945
22946
22947
22948
22949
22950
22951
22952
22953
22954
22955
22956
22957
22958
22959
22960
22961
22962
22963
22964
22965
22966
22967
22968
22969
22970
22971
22972
22973
22974
22975
22976
22977
22978
22979
22980
22981
22982
22983
22984
22985
22986
22987
22988
22989
22990
22991
22992
22993
22994
22995
22996
22997
22998
22999
23000
23001
23002
23003
23004
23005
23006
23007
23008
23009
23010
23011
23012
23013
23014
23015
23016
23017
23018
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037
23038
23039
23040
23041
23042
23043
23044
23045
23046
23047
23048
23049
23050
23051
23052
23053
23054
23055
23056
23057
23058
23059
23060
23061
23062
23063
23064
23065
23066
23067
23068
23069
23070
23071
23072
23073
23074
23075
23076
23077
23078
23079
23080
23081
23082
23083
23084
23085
23086
23087
23088
23089
23090
23091
23092
23093
23094
23095
23096
23097
23098
23099
23100
23101
23102
23103
23104
23105
23106
23107
23108
23109
23110
23111
23112
23113
23114
23115
23116
23117
23118
23119
23120
23121
23122
23123
23124
23125
23126
23127
23128
23129
23130
23131
23132
23133
23134
23135
23136
23137
23138
23139
23140
23141
23142
23143
23144
23145
23146
23147
23148
23149
23150
23151
23152
23153
23154
23155
23156
23157
23158
23159
23160
23161
23162
23163
23164
23165
23166
23167
23168
23169
23170
23171
23172
23173
23174
23175
23176
23177
23178
23179
23180
23181
23182
23183
23184
23185
23186
23187
23188
23189
23190
23191
23192
23193
23194
23195
23196
23197
23198
23199
23200
23201
23202
23203
23204
23205
23206
23207
23208
23209
23210
23211
23212
23213
23214
23215
23216
23217
23218
23219
23220
23221
23222
23223
23224
23225
23226
23227
23228
23229
23230
23231
23232
23233
23234
23235
23236
23237
23238
23239
23240
23241
23242
23243
23244
23245
23246
23247
23248
23249
23250
23251
23252
23253
23254
23255
23256
23257
23258
23259
23260
23261
23262
23263
23264
23265
23266
23267
23268
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279
23280
23281
23282
23283
23284
23285
23286
23287
23288
23289
23290
23291
23292
23293
23294
23295
23296
23297
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326
23327
23328
23329
23330
23331
23332
23333
23334
23335
23336
23337
23338
23339
23340
23341
23342
23343
23344
23345
23346
23347
23348
23349
23350
23351
23352
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381
23382
23383
23384
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394
23395
23396
23397
23398
23399
23400
23401
23402
23403
23404
23405
23406
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416
23417
23418
23419
23420
23421
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437
23438
23439
23440
23441
23442
23443
23444
23445
23446
23447
23448
23449
23450
23451
23452
23453
23454
23455
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466
23467
23468
23469
23470
23471
23472
23473
23474
23475
23476
23477
23478
23479
23480
23481
23482
23483
23484
23485
23486
23487
23488
23489
23490
23491
23492
23493
23494
23495
23496
23497
23498
23499
23500
23501
23502
23503
23504
23505
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515
23516
23517
23518
23519
23520
23521
23522
23523
23524
23525
23526
23527
23528
23529
23530
23531
23532
23533
23534
23535
23536
23537
23538
23539
23540
23541
23542
23543
23544
23545
23546
23547
23548
23549
23550
23551
23552
23553
23554
23555
23556
23557
23558
23559
23560
23561
23562
23563
23564
23565
23566
23567
23568
23569
23570
23571
23572
23573
23574
23575
23576
23577
23578
23579
23580
23581
23582
23583
23584
23585
23586
23587
23588
23589
23590
23591
23592
23593
23594
23595
23596
23597
23598
23599
23600
23601
23602
23603
23604
23605
23606
23607
23608
23609
23610
23611
23612
23613
23614
23615
23616
23617
23618
23619
23620
23621
23622
23623
23624
23625
23626
23627
23628
23629
23630
23631
23632
23633
23634
23635
23636
23637
23638
23639
23640
23641
23642
23643
23644
23645
23646
23647
23648
23649
23650
23651
23652
23653
23654
23655
23656
23657
23658
23659
23660
23661
23662
23663
23664
23665
23666
23667
23668
23669
23670
23671
23672
23673
23674
23675
23676
23677
23678
23679
23680
23681
23682
23683
23684
23685
23686
23687
23688
23689
23690
23691
23692
23693
23694
23695
23696
23697
23698
23699
23700
23701
23702
23703
23704
23705
23706
23707
23708
23709
23710
23711
23712
23713
23714
23715
23716
23717
23718
23719
23720
23721
23722
23723
23724
23725
23726
23727
23728
23729
23730
23731
23732
23733
23734
23735
23736
23737
23738
23739
23740
23741
23742
23743
23744
23745
23746
23747
23748
23749
23750
23751
23752
23753
23754
23755
23756
23757
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
23770
23771
23772
23773
23774
23775
23776
23777
23778
23779
23780
23781
23782
23783
23784
23785
23786
23787
23788
23789
23790
23791
23792
23793
23794
23795
23796
23797
23798
23799
23800
23801
23802
23803
23804
23805
23806
23807
23808
23809
23810
23811
23812
23813
23814
23815
23816
23817
23818
23819
23820
23821
23822
23823
23824
23825
23826
23827
23828
23829
23830
23831
23832
23833
23834
23835
23836
23837
23838
23839
23840
23841
23842
23843
23844
23845
23846
23847
23848
23849
23850
23851
23852
23853
23854
23855
23856
23857
23858
23859
23860
23861
23862
23863
23864
23865
23866
23867
23868
23869
23870
23871
23872
23873
23874
23875
23876
23877
23878
23879
23880
23881
23882
23883
23884
23885
23886
23887
23888
23889
23890
23891
23892
23893
23894
23895
23896
23897
23898
23899
23900
23901
23902
23903
23904
23905
23906
23907
23908
23909
23910
23911
23912
23913
23914
23915
23916
23917
23918
23919
23920
23921
23922
23923
23924
23925
23926
23927
23928
23929
23930
23931
23932
23933
23934
23935
23936
23937
23938
23939
23940
23941
23942
23943
23944
23945
23946
23947
23948
23949
23950
23951
23952
23953
23954
23955
23956
23957
23958
23959
23960
23961
23962
23963
23964
23965
23966
23967
23968
23969
23970
23971
23972
23973
23974
23975
23976
23977
23978
23979
23980
23981
23982
23983
23984
23985
23986
23987
23988
23989
23990
23991
23992
23993
23994
23995
23996
23997
23998
23999
24000
24001
24002
24003
24004
24005
24006
24007
24008
24009
24010
24011
24012
24013
24014
24015
24016
24017
24018
24019
24020
24021
24022
24023
24024
24025
24026
24027
24028
24029
24030
24031
24032
24033
24034
24035
24036
24037
24038
24039
24040
24041
24042
24043
24044
24045
24046
24047
24048
24049
24050
24051
24052
24053
24054
24055
24056
24057
24058
24059
24060
24061
24062
24063
24064
24065
24066
24067
24068
24069
24070
24071
24072
24073
24074
24075
24076
24077
24078
24079
24080
24081
24082
24083
24084
24085
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115
24116
24117
24118
24119
24120
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136
24137
24138
24139
24140
24141
24142
24143
24144
24145
24146
24147
24148
24149
24150
24151
24152
24153
24154
24155
24156
24157
24158
24159
24160
24161
24162
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180
24181
24182
24183
24184
24185
24186
24187
24188
24189
24190
24191
24192
24193
24194
24195
24196
24197
24198
24199
24200
24201
24202
24203
24204
24205
24206
24207
24208
24209
24210
24211
24212
24213
24214
24215
24216
24217
24218
24219
24220
24221
24222
24223
24224
24225
24226
24227
24228
24229
24230
24231
24232
24233
24234
24235
24236
24237
24238
24239
24240
24241
24242
24243
24244
24245
24246
24247
24248
24249
24250
24251
24252
24253
24254
24255
24256
24257
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270
24271
24272
24273
24274
24275
24276
24277
24278
24279
24280
24281
24282
24283
24284
24285
24286
24287
24288
24289
24290
24291
24292
24293
24294
24295
24296
24297
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319
24320
24321
24322
24323
24324
24325
24326
24327
24328
24329
24330
24331
24332
24333
24334
24335
24336
24337
24338
24339
24340
24341
24342
24343
24344
24345
24346
24347
24348
24349
24350
24351
24352
24353
24354
24355
24356
24357
24358
24359
24360
24361
24362
24363
24364
24365
24366
24367
24368
24369
24370
24371
24372
24373
24374
24375
24376
24377
24378
24379
24380
24381
24382
24383
24384
24385
24386
24387
24388
24389
24390
24391
24392
24393
24394
24395
24396
24397
24398
24399
24400
24401
24402
24403
24404
24405
24406
24407
24408
24409
24410
24411
24412
24413
24414
24415
24416
24417
24418
24419
24420
24421
24422
24423
24424
24425
24426
24427
24428
24429
24430
24431
24432
24433
24434
24435
24436
24437
24438
24439
24440
24441
24442
24443
24444
24445
24446
24447
24448
24449
24450
24451
24452
24453
24454
24455
24456
24457
24458
24459
24460
24461
24462
24463
24464
24465
24466
24467
24468
24469
24470
24471
24472
24473
24474
24475
24476
24477
24478
24479
24480
24481
24482
24483
24484
24485
24486
24487
24488
24489
24490
24491
24492
24493
24494
24495
24496
24497
24498
24499
24500
24501
24502
24503
24504
24505
24506
24507
24508
24509
24510
24511
24512
24513
24514
24515
24516
24517
24518
24519
24520
24521
24522
24523
24524
24525
24526
24527
24528
24529
24530
24531
24532
24533
24534
24535
24536
24537
24538
24539
24540
24541
24542
24543
24544
24545
24546
24547
24548
24549
24550
24551
24552
24553
24554
24555
24556
24557
24558
24559
24560
24561
24562
24563
24564
24565
24566
24567
24568
24569
24570
24571
24572
24573
24574
24575
24576
24577
24578
24579
24580
24581
24582
24583
24584
24585
24586
24587
24588
24589
24590
24591
24592
24593
24594
24595
24596
24597
24598
24599
24600
24601
24602
24603
24604
24605
24606
24607
24608
24609
24610
24611
24612
24613
24614
24615
24616
24617
24618
24619
24620
24621
24622
24623
24624
24625
24626
24627
24628
24629
24630
24631
24632
24633
24634
24635
24636
24637
24638
24639
24640
24641
24642
24643
24644
24645
24646
24647
24648
24649
24650
24651
24652
24653
24654
24655
24656
24657
24658
24659
24660
24661
24662
24663
24664
24665
24666
24667
24668
24669
24670
24671
24672
24673
24674
24675
24676
24677
24678
24679
24680
24681
24682
24683
24684
24685
24686
24687
24688
24689
24690
24691
24692
24693
24694
24695
24696
24697
24698
24699
24700
24701
24702
24703
24704
24705
24706
24707
24708
24709
24710
24711
24712
24713
24714
24715
24716
24717
24718
24719
24720
24721
24722
24723
24724
24725
24726
24727
24728
24729
24730
24731
24732
24733
24734
24735
24736
24737
24738
24739
24740
24741
24742
24743
24744
24745
24746
24747
24748
24749
24750
24751
24752
24753
24754
24755
24756
24757
24758
24759
24760
24761
24762
24763
24764
24765
24766
24767
24768
24769
24770
24771
24772
24773
24774
24775
24776
24777
24778
24779
24780
24781
24782
24783
24784
24785
24786
24787
24788
24789
24790
24791
24792
24793
24794
24795
24796
24797
24798
24799
24800
24801
24802
24803
24804
24805
24806
24807
24808
24809
24810
24811
24812
24813
24814
24815
24816
24817
24818
24819
24820
24821
24822
24823
24824
24825
24826
24827
24828
24829
24830
24831
24832
24833
24834
24835
24836
24837
24838
24839
24840
24841
24842
24843
.....
25059
25060
25061
25062
25063
25064
25065
25066
25067
25068
25069
25070
25071
25072
25073
.....
25094
25095
25096
25097
25098
25099
25100
25101
25102
25103
25104
25105
25106
25107
25108
.....
25347
25348
25349
25350
25351
25352
25353









25354
25355
25356
25357
25358
25359
25360
.....
25459
25460
25461
25462
25463
25464
25465
25466
25467
25468
25469
25470
25471
25472
25473
.....
26603
26604
26605
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
.....
26682
26683
26684
26685
26686
26687
26688
26689
26690
26691
26692
26693
26694
26695
26696
.....
27881
27882
27883
27884
27885
27886
27887
27888
27889
27890
27891
27892
27893
27894
27895
.....
28185
28186
28187
28188
28189
28190
28191
28192
28193
28194
28195
28196
28197
28198
28199
.....
28476
28477
28478
28479
28480
28481
28482
28483
28484
28485
28486
28487
28488
28489
28490
.....
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643
28644
28645
28646
28647
.....
28984
28985
28986
28987
28988
28989
28990
28991
28992
28993
28994
28995
28996
28997
28998
28999
29000
29001
29002
29003
29004
29005
.....
30197
30198
30199
30200
30201
30202
30203
30204
30205
30206
30207
30208
30209
30210
30211
30212
30213
30214
30215
30216
30217
.....
32164
32165
32166
32167
32168
32169
32170







32171
32172
32173
32174
32175
32176








32177
32178
32179
32180
32181
32182
32183
.....
32219
32220
32221
32222
32223
32224
32225







32226
32227
32228
32229
32230



















32231
32232
32233
32234
32235
32236
32237
.....
32308
32309
32310
32311
32312
32313
32314
32315
32316
32317
32318
32319
32320
32321
32322
32323
32324
32325
32326
32327
32328
32329
32330
32331
32332
32333
32334
32335
32336

32337
32338


32339
32340
32341
32342
32343


32344
32345
32346
32347
32348
32349
32350
32351
32352
32353
32354
32355
32356
32357
32358
32359
32360
32361
32362
32363
32364
32365




32366
32367
32368
32369
32370
32371
32372
.....
32389
32390
32391
32392
32393
32394
32395
32396
32397
32398
32399
32400
32401
32402
32403
32404
32405
32406
32407
32408
32409
32410
32411
32412
32413
32414
32415
32416
32417
32418
32419
32420
32421
32422
32423
32424
32425
32426
32427
32428
32429
32430
32431
32432
32433
32434
32435
32436
32437
32438
32439
32440
32441
32442
32443
32444
32445
32446
32447
32448
32449
32450
32451
32452
32453
32454
32455
32456
32457
32458
32459
32460
32461
32462
32463
32464
32465
32466
32467
32468
32469
32470
32471
32472
32473
32474
32475
32476
32477
32478
32479
32480
32481
32482
32483
32484
32485
32486
32487
32488
32489
32490
32491
32492
32493
32494
32495
32496
32497
32498
32499
32500
32501
32502
32503
32504
32505
32506
32507
32508
32509
32510
32511
32512
32513
32514
32515
32516
32517
32518
32519
32520
32521
32522
32523
32524
32525
32526
32527
32528
32529
32530
32531
32532
32533
32534

32535



32536
32537
32538
32539
32540
32541
32542
32543
32544
32545
32546
32547
32548
32549
32550
32551
32552
32553
32554
32555
32556
32557
32558
32559
32560
32561
32562
32563
32564
32565
32566
32567
32568
32569
32570
32571
32572

32573



32574
32575
32576
32577
32578
32579
32580
32581
32582
32583
32584
32585
32586
32587
32588
32589
32590
32591
32592
32593
32594
32595
32596
32597
32598
32599
32600
32601
32602
32603
32604
32605

32606



32607
32608
32609
32610
32611
32612
32613
32614
32615
32616
32617
32618
32619
32620
32621
32622
32623

32624



32625
32626
32627
32628

32629



32630
32631
32632
32633
32634
32635
32636
32637
32638
32639
32640
32641
32642
32643
32644
32645
32646

32647



32648
32649
32650
32651
32652
32653
32654
32655
32656
32657
32658
32659
32660
32661
32662
32663
32664
32665
32666
32667

32668



32669
32670
32671
32672
32673
32674
32675
32676
32677
32678
32679





32680
32681
32682
32683
32684
32685
32686
32687
32688
32689






32690



32691
32692
32693
32694
32695
32696
32697
32698
32699
32700
32701
32702
32703
32704
32705
32706
32707
32708
32709
32710
32711
32712
32713

32714



32715
32716
32717
32718

32719



32720
32721
32722
32723
32724
32725
32726
32727
32728
32729
32730
32731
32732
32733
32734
32735





32736
32737
32738
32739
32740
32741
32742
32743
32744



32745
32746
32747
32748
32749
32750
32751
32752
32753
32754
32755
32756
32757









32758













































































































32759
32760
32761
32762
32763
32764
32765
.....
32837
32838
32839
32840
32841
32842
32843


























































32844
32845
32846
32847
32848
32849
32850
32851
32852
32853
32854
32855
32856
32857
32858
32859
32860
32861
32862
32863
.....
32875
32876
32877
32878
32879
32880
32881
32882
32883
32884
32885
32886
32887
32888
32889
.....
32897
32898
32899
32900
32901
32902
32903
32904
32905
32906
32907
32908
32909
32910
32911
.....
32918
32919
32920
32921
32922
32923
32924
32925
32926
32927
32928
32929
32930
32931
32932
.....
32946
32947
32948
32949
32950
32951
32952
32953
32954
32955
32956
32957
32958
32959
32960
.....
32974
32975
32976
32977
32978
32979
32980


32981
32982
32983
32984
32985
32986
32987
32988
32989
32990
32991
32992

32993










32994
32995
32996
32997
32998
32999
33000
33001
33002
33003
.....
33004
33005
33006
33007
33008
33009
33010
33011
33012
33013
33014
33015
33016
33017
33018
.....
33204
33205
33206
33207
33208
33209
33210











33211
33212
33213
33214
33215
33216
33217
33218
33219
33220

33221
33222
33223
33224
33225

33226
33227

33228
33229
33230
33231
33232
33233


33234
33235
33236
33237
33238
33239
33240
33241
.....
33246
33247
33248
33249
33250
33251
33252
33253
33254

33255
33256
33257
33258
33259
33260
33261
.....
33330
33331
33332
33333
33334
33335
33336
33337
33338
33339
33340
33341
33342
33343
33344
.....
33391
33392
33393
33394
33395
33396
33397
33398
33399
33400
33401
33402
33403
33404
33405
.....
33522
33523
33524
33525
33526
33527
33528
33529
33530
33531
33532
33533
33534
33535
33536
.....
33586
33587
33588
33589
33590
33591
33592
33593
33594
33595
33596
33597
33598
33599
33600
.....
33643
33644
33645
33646
33647
33648
33649




33650
33651
33652

33653
33654
33655
33656
33657
33658
33659
33660



33661
33662
33663

















33664
33665
33666
33667
33668
33669
33670

33671
33672
33673
33674
33675
33676









33677



















33678
33679
33680
33681
33682
33683
33684
.....
33690
33691
33692
33693
33694
33695
33696

33697
33698
33699
33700
33701
33702
33703
.....
33716
33717
33718
33719
33720
33721
33722




















33723
33724
33725
33726
33727
33728
33729
.....
33739
33740
33741
33742
33743
33744
33745
33746
33747
33748
33749
33750
33751
33752
33753
33754
33755
33756
33757
33758
33759
33760
33761
33762
33763
33764
.....
34005
34006
34007
34008
34009
34010
34011
34012
34013
34014
34015

34016
34017
34018


















34019

34020
34021
34022
34023
34024
34025
34026
34027


34028
34029
34030
34031
34032
34033
34034
34035
34036
























34037
34038
34039
34040
34041
34042
34043
34044
34045
34046
34047
34048
34049
34050
34051
34052



34053



34054



34055
34056
34057
34058

34059
34060
34061

34062
34063
34064
34065
34066
34067
34068
.....
34069
34070
34071
34072
34073
34074
34075
34076
34077
34078
34079


34080
34081
34082

34083

34084
34085
34086
34087
34088
34089
34090
.....
34147
34148
34149
34150
34151
34152
34153

34154
34155
34156
34157
34158
34159
34160
34161
34162
34163
34164
34165
34166
34167
34168
34169
.....
34179
34180
34181
34182
34183
34184
34185
34186
34187
34188
34189
34190
34191
34192
34193
.....
34200
34201
34202
34203
34204
34205
34206

34207
34208
34209
34210
34211
34212
34213
34214
34215
34216
34217
34218
34219
34220
34221
34222
34223
34224
34225
34226
34227
34228
.....
34248
34249
34250
34251
34252
34253
34254
34255
34256
34257
34258
34259
34260
34261
34262
34263
34264
.....
34280
34281
34282
34283
34284
34285
34286
34287
34288
34289
34290
34291
34292
34293
34294
34295
34296
34297
34298
34299
34300
34301
34302
34303
34304
34305
34306
34307
34308
34309
.....
34533
34534
34535
34536
34537
34538
34539
34540
34541
34542
34543
34544
34545
34546
34547
34548
34549
34550
34551
34552
34553
34554
34555
34556

34557



34558
34559
34560
34561
34562
34563
34564
34565
.....
34989
34990
34991
34992
34993
34994
34995





34996
34997
34998

34999
35000
35001
35002
35003
35004





35005
35006
35007

35008
35009
35010
35011
35012
35013
35014
.....
35086
35087
35088
35089
35090
35091
35092
35093
35094
35095


35096
35097
35098
35099

35100
35101
35102
35103
35104
35105
35106
.....
35107
35108
35109
35110
35111
35112
35113

35114
35115
35116
35117
35118
35119
35120
35121


35122
35123


35124
35125
35126
35127
35128
35129
35130
35131
35132
35133
35134
35135

35136
35137
35138
35139
35140
35141
35142
35143
35144
35145
35146
35147
35148
35149
35150
35151
35152


35153
35154
35155
35156


35157
35158
35159
35160
35161
35162
35163
35164
35165

35166
35167
35168
35169
35170
35171
35172
35173
35174
35175
35176





























35177
35178
35179
35180
35181
35182
35183
.....
35276
35277
35278
35279
35280
35281
35282





35283
35284
35285
35286
35287
35288
35289
.....
35320
35321
35322
35323
35324
35325
35326


















35327
35328
35329
35330
35331
35332
35333
35334
35335

35336
35337

35338
35339
35340
35341
35342
35343
35344
35345
35346
35347

35348
35349

35350
35351
35352
35353
35354
35355
35356
.....
35419
35420
35421
35422
35423
35424
35425

35426
35427
35428
35429
35430
35431
35432
35433
35434
35435
35436
35437











35438













35439
35440
35441
35442
35443
35444
35445






35446
35447

35448












35449
35450
35451


35452



35453
35454
35455
35456
35457
35458
35459
.....
35505
35506
35507
35508
35509
35510
35511
35512

35513
35514
35515
35516
35517
35518
35519
35520

35521
35522
35523
35524
35525
35526
35527
.....
35531
35532
35533
35534
35535
35536
35537





































35538
35539
35540
35541
35542
35543
35544
.....
35547
35548
35549
35550
35551
35552
35553




















35554

35555
35556
35557
35558
35559
35560
35561











35562

35563
35564
35565
35566
35567
35568
35569
35570
35571
35572
35573
.....
35577
35578
35579
35580
35581
35582
35583
35584










35585
35586
35587
35588
35589
35590
35591
.....
35594
35595
35596
35597
35598
35599
35600
35601

35602
35603
35604
35605
35606
35607
35608
35609
35610
35611
35612
35613
35614
35615
35616
35617
35618
35619

35620
35621
35622
35623
35624
35625
35626
35627
35628
.....
35640
35641
35642
35643
35644
35645
35646
35647
35648
35649
35650
35651
35652
35653
35654
35655
35656

35657
35658
35659
35660
35661
35662
35663
.....
35694
35695
35696
35697
35698
35699
35700







35701
35702
35703
35704
35705

35706
35707
35708
35709
35710
35711
35712
.....
35714
35715
35716
35717
35718
35719
35720
35721
35722
35723
35724
35725
35726
35727
35728
.....
35856
35857
35858
35859
35860
35861
35862
35863
35864
35865
35866
35867



35868

35869
35870
35871
35872
35873
35874
35875
35876






35877
35878
35879
35880
35881
35882
35883
.....
37121
37122
37123
37124
37125
37126
37127

37128
37129
37130
37131
37132
37133

37134
37135
37136
37137
37138
37139
37140
.....
37153
37154
37155
37156
37157
37158
37159

37160
37161
37162

37163
37164
37165
37166
37167
37168
37169
.....
41581
41582
41583
41584
41585
41586
41587
41588
41589
41590
41591
41592
41593
41594
41595
.....
42938
42939
42940
42941
42942
42943
42944




42945

42946
42947
42948
42949
42950
42951
42952
42953
42954
42955
42956
42957
42958
42959
42960
42961
42962
42963
.....
42973
42974
42975
42976
42977
42978
42979
42980
42981
42982
42983
42984
42985
42986
42987
.....
43003
43004
43005
43006
43007
43008
43009
43010
43011
43012
43013
43014
43015
43016
43017
.....
43019
43020
43021
43022
43023
43024
43025
43026
43027
43028
43029
43030
43031
43032
43033
43034
43035
43036
43037
43038
43039
43040
43041
43042
43043
.....
44874
44875
44876
44877
44878
44879
44880







44881
44882
44883
44884
44885
44886
44887
44888
44889
44890
.....
51261
51262
51263
51264
51265
51266
51267
51268

51269
51270
51271
51272
51273
51274
51275
.....
51297
51298
51299
51300
51301
51302
51303
51304
51305
51306
51307
51308
51309
51310
51311
51312
51313



51314

51315
51316
51317
51318

51319
51320
51321
51322
51323
51324
51325
51326
51327
51328
51329
51330
51331
51332
51333
51334
51335
.....
57586
57587
57588
57589
57590
57591
57592
57593

57594
57595
57596
57597
57598
57599
57600
57601
57602
57603
57604
57605
57606
57607
.....
58244
58245
58246
58247
58248
58249
58250
58251
58252
58253
58254
58255
58256
58257
58258
.....
58373
58374
58375
58376
58377
58378
58379
58380
58381
58382
58383
58384
58385
58386
58387
58388
58389
58390
58391
58392
58393
58394
.....
58406
58407
58408
58409
58410
58411
58412
58413
58414
58415
58416
58417
58418
58419
58420
58421
58422
58423
58424
58425
58426
58427
58428
58429
.....
62179
62180
62181
62182
62183
62184
62185

62186
62187
62188
62189
62190
62191
62192
.....
63018
63019
63020
63021
63022
63023
63024
63025
63026
63027
63028
63029
63030
63031
63032
63033
63034
63035

63036
63037
63038
63039
63040
63041
63042
.....
64429
64430
64431
64432
64433
64434
64435

64436
64437
64438
64439
64440
64441
64442
64443
64444
.....
67828
67829
67830
67831
67832
67833
67834
67835
67836
67837
67838
67839
67840
67841
67842
.....
68142
68143
68144
68145
68146
68147
68148
68149
68150
68151
68152
68153
68154
68155
68156
.....
69335
69336
69337
69338
69339
69340
69341
69342
69343
69344
69345
69346
69347
69348
69349
.....
70011
70012
70013
70014
70015
70016
70017
70018
70019
70020
70021
70022
70023
70024
70025
.....
70678
70679
70680
70681
70682
70683
70684
70685
70686
70687
70688
70689
70690
70691
70692
.....
71344
71345
71346
71347
71348
71349
71350
71351
71352
71353
71354
71355
71356
71357
71358
.....
73699
73700
73701
73702
73703
73704
73705
73706
73707
73708
73709
73710
73711
73712
73713
.....
73944
73945
73946
73947
73948
73949
73950
73951
73952
73953
73954
73955
73956
73957
73958
73959
73960
73961
73962
73963
73964
73965
73966
73967
73968
73969
73970
73971
73972
73973
73974
73975
73976
.....
73977
73978
73979
73980
73981
73982
73983
73984
73985
73986
73987
73988
73989
73990
73991
73992
73993
73994
73995
73996
73997
73998
73999
74000
74001
74002
74003
74004
74005
.....
74073
74074
74075
74076
74077
74078
74079
74080
74081
74082
74083
74084
74085
74086
74087
.....
74271
74272
74273
74274
74275
74276
74277
74278
74279
74280
74281
74282
74283
74284
74285
.....
74307
74308
74309
74310
74311
74312
74313





74314
74315
74316
74317
74318
74319
74320
.....
74370
74371
74372
74373
74374
74375
74376
74377
74378
74379
74380
74381
74382
74383
74384
.....
74416
74417
74418
74419
74420
74421
74422
74423
74424
74425
74426
74427
74428
74429
74430
74431
74432
74433
.....
74448
74449
74450
74451
74452
74453
74454
74455
74456
74457
74458
74459
74460
74461
74462
.....
74536
74537
74538
74539
74540
74541
74542
74543
74544
74545
74546
74547
74548
74549
74550
74551
74552
74553
74554
74555
74556
74557
74558
74559
74560
74561
74562
74563
74564
74565
74566
74567
74568
74569
74570
74571
74572
74573
74574
74575
74576
74577
74578
74579
74580
74581
74582
74583
74584
74585
74586
74587
74588
74589
74590
74591
.....
78391
78392
78393
78394
78395
78396
78397
78398
78399
78400
78401
78402
78403
78404
78405
.....
78578
78579
78580
78581
78582
78583
78584

78585

78586
78587
78588
78589
78590
78591
78592
.....
78615
78616
78617
78618
78619
78620
78621
78622
78623

78624
78625
78626
78627
78628


78629
78630
78631
78632
78633
78634
78635
.....
80898
80899
80900
80901
80902
80903
80904
80905
80906
80907
80908
80909
80910
80911
80912
.....
80970
80971
80972
80973
80974
80975
80976
80977
80978
80979
80980
80981
80982
80983
80984
.....
81886
81887
81888
81889
81890
81891
81892
81893
81894
81895
81896
81897
81898
81899
81900
81901


81902
81903
81904
81905
81906
81907
81908
81909
81910
81911
81912
81913
81914
81915
81916
81917
81918
81919
81920
81921
81922
81923
81924
81925
81926
81927
81928
81929
81930
81931
81932
81933
81934
81935
81936
81937
81938
81939
81940
81941
81942
81943
81944
81945
81946
81947
81948
81949
81950
81951
.....
81958
81959
81960
81961
81962
81963
81964













































81965
81966
81967
81968
81969
81970
81971
.....
81994
81995
81996
81997
81998
81999
82000






82001
82002
82003

82004
82005
82006
82007
82008
82009






82010
82011
82012
82013
82014
82015
82016
.....
82035
82036
82037
82038
82039
82040
82041



82042
82043
82044
82045
82046
82047
82048
.....
82983
82984
82985
82986
82987
82988
82989
82990
82991
82992
82993
82994
82995
82996
82997
.....
84239
84240
84241
84242
84243
84244
84245
84246
84247
84248
84249
84250
84251
84252
84253
.....
87310
87311
87312
87313
87314
87315
87316
87317











87318
87319
87320
87321
87322
87323
87324
87325
.....
92514
92515
92516
92517
92518
92519
92520
92521
92522
92523
92524
92525
92526
92527
92528
.....
93199
93200
93201
93202
93203
93204
93205












































93206
93207
93208
93209
93210
93211
93212
.....
94232
94233
94234
94235
94236
94237
94238
94239
94240
94241
94242
94243
94244
94245
94246
.....
94312
94313
94314
94315
94316
94317
94318
94319
94320
94321
94322
94323
94324
94325
94326
.....
94365
94366
94367
94368
94369
94370
94371
94372
94373
94374
94375
94376
94377
94378
94379
94380
94381
94382
94383
94384
94385
94386
94387
94388
94389
94390
94391
94392
.....
94446
94447
94448
94449
94450
94451
94452
94453
94454
94455
94456
94457
94458
94459
94460
.....
94676
94677
94678
94679
94680
94681
94682

94683
94684
94685
94686
94687
94688
94689
.....
97983
97984
97985
97986
97987
97988
97989

97990
97991
97992
97993
97994
97995
97996
.....
98973
98974
98975
98976
98977
98978
98979

98980

98981
98982
98983
98984
98985
98986
98987
......
101795
101796
101797
101798
101799
101800
101801
101802
101803
101804
101805
101806
101807
101808
101809
......
101827
101828
101829
101830
101831
101832
101833
101834
101835
101836
101837
101838
101839
101840
101841
101842
......
101843
101844
101845
101846
101847
101848
101849

101850
101851
101852
101853
101854




101855
101856
101857
101858
101859
101860
101861
101862
101863
101864
101865
101866
101867
101868
101869
101870
101871

101872
101873
101874
101875

101876


101877
101878
101879
101880
101881
101882
101883
......
101984
101985
101986
101987
101988
101989
101990

























101991
101992
101993
101994
101995
101996
101997
......
102252
102253
102254
102255
102256
102257
102258
102259
102260
102261
102262
102263
102264
102265
102266
......
102277
102278
102279
102280
102281
102282
102283

102284
102285
102286
102287
102288
102289
102290
102291
102292
102293
......
104436
104437
104438
104439
104440
104441
104442



104443
104444
104445
104446
104447
104448
104449
104450
104451

104452
104453
104454
104455
104456
104457
104458
......
104592
104593
104594
104595
104596
104597
104598
104599



104600
104601
104602
104603
104604
104605











104606
104607
104608
104609
104610
104611
104612
104613
......
108353
108354
108355
108356
108357
108358
108359
108360
108361
108362
108363
108364
108365
108366
108367
......
108423
108424
108425
108426
108427
108428
108429
108430
108431
108432
108433
108434
108435
108436
108437
108438
108439
108440
108441
108442
108443
108444
108445
108446
108447
108448
108449
108450
108451
108452
108453
108454
108455
108456
108457
108458
108459
108460
108461
108462
108463
108464
108465
108466
108467
108468
108469
108470
108471
108472
108473
108474
108475
108476
108477
108478
108479
108480
108481
108482
108483
108484
108485
108486
108487
108488
108489
108490
108491
108492
108493
108494
108495
108496
108497
108498
108499
108500
108501
108502
108503
108504
108505
108506
108507
108508
108509
108510
108511
108512
108513
108514
108515
108516
108517
108518
108519
108520
108521
108522
108523
108524
108525
108526
108527
108528
108529
108530
108531
108532
108533
108534
108535
108536
108537
108538
108539
108540
108541
108542
108543
108544
108545
108546
108547
108548
108549
108550
108551
108552
108553
108554
108555
108556
108557
108558
108559
108560
108561
108562
108563
108564
108565
108566
108567
108568
108569
108570
108571
108572
108573
108574
108575
108576
108577
108578
108579
108580
108581
108582
108583
108584
108585
108586
108587
108588
108589
108590
108591
108592
108593
108594
108595
108596
108597
108598
108599
108600
108601
108602
108603
108604
108605
108606
108607
108608
108609
108610
108611
108612
108613
108614
108615
108616
108617
108618
108619
108620
108621
108622
108623
108624
108625
108626
108627
108628
108629
108630
108631
108632
108633
108634
108635
108636
108637
108638
108639
108640
108641
108642
108643
108644
108645
108646
108647
108648
108649
108650
108651
108652
108653
108654
108655
108656
108657
108658
108659
108660
108661
108662
108663
108664
108665
108666
108667
108668
108669
108670
108671
108672
108673
108674
108675
108676
108677
108678
108679
108680
108681
108682
108683
108684
108685
108686
108687
108688
108689
108690
108691
108692
108693
108694
108695
108696
108697
108698
108699
108700
108701
108702
108703
108704
108705
108706
108707
108708
108709
108710
108711
108712
108713
108714
108715
108716
108717
108718
108719
108720
108721
108722
108723
108724
108725
108726
108727
108728
108729
108730
108731
108732
108733
108734
108735
108736
108737
108738
108739
108740
108741
108742
108743
108744
108745
108746
108747
108748
108749
108750
108751
108752
108753
108754
108755
108756
108757
108758
108759
108760
108761
108762
108763
108764
108765
108766
108767
108768
108769
108770
108771
108772
108773
108774
108775
108776
108777
108778
108779
108780
108781
108782
108783
108784
108785
108786
108787
108788
108789
108790
108791
108792
108793
108794
108795
108796
108797
108798
108799
108800
108801
108802
108803
108804
108805
108806
108807
108808
108809
108810
108811
108812
108813
108814
108815
108816
108817
108818
108819
108820
108821
108822
108823
108824
108825
108826
108827
108828
108829
108830
108831
108832
108833
108834
108835
108836
108837
108838
108839
108840
108841
108842
108843
108844
108845
108846
108847
108848
108849
108850
108851
108852
108853
108854
108855
108856
108857
108858
108859
108860
108861
108862
108863
108864
108865
108866
108867
108868
108869
108870
108871
108872
108873
108874
108875
108876
108877
108878
108879
108880
108881
108882
108883
108884
108885
108886
108887
108888
108889
108890
108891
108892
108893
108894
108895
108896
108897
108898
108899
108900
108901
108902
......
109093
109094
109095
109096
109097
109098
109099
109100
109101
109102
109103
109104
109105
109106
109107
109108
109109
109110
......
109173
109174
109175
109176
109177
109178
109179
109180
109181
109182
109183
109184
109185
109186
109187
109188
109189
109190
109191
109192
109193
109194
109195
109196
109197
109198
109199
109200
109201
109202
109203
109204
109205
109206
109207
109208
109209
109210
109211
109212
109213
109214
109215
109216

109217
109218


109219
109220
109221
109222
109223
109224
109225
109226
109227
109228
109229
109230
109231
109232
109233
109234
109235
109236
109237
109238
109239
109240
109241
109242
109243
109244
109245
109246
109247
109248
109249
109250
109251
109252
109253
109254
109255
109256
109257
109258
109259
109260
109261
109262
109263
109264
109265
109266
109267
109268
109269
109270
109271
109272
109273
109274
109275
109276
109277
109278
109279
109280
109281
109282
109283
109284
109285
109286
109287
109288
109289
109290
109291
109292
109293
109294
109295
109296
109297
109298
109299
109300
109301
109302
109303
109304
109305
109306
109307
109308
109309
109310
109311
109312
109313
109314
109315
109316
109317
109318
109319
109320
109321
109322
109323
109324
109325
109326
109327
109328
109329
109330
109331
109332
109333
109334
109335
109336
109337
109338
109339
109340
109341
109342
109343
109344
109345
109346
109347
109348
109349
109350
109351
109352
109353
109354
109355
109356
109357
109358
109359
109360
109361
109362
109363
109364
109365
109366
109367
109368
109369
109370
109371
109372
109373
109374
109375
109376
109377
109378
109379
109380
109381
109382
109383
109384
109385
109386
109387
109388
109389
109390
109391
109392
109393
109394
109395
109396
109397
109398
109399
109400
109401
109402
109403
109404
109405
109406
109407
109408
109409
109410
109411
109412
109413
109414
109415
109416
109417
109418
109419
109420
109421
109422
109423
109424
109425
109426
109427
109428
109429
109430
109431
109432
109433
109434
109435
109436
109437
109438
109439
109440
109441
109442
109443
109444
109445
109446
109447
109448
109449
109450
109451
109452
109453
109454
109455
109456
109457
109458
......
109529
109530
109531
109532
109533
109534
109535
109536
109537
109538
109539
109540
109541
109542
109543
109544
109545
109546
109547
109548
109549
......
109890
109891
109892
109893
109894
109895
109896
109897
109898
109899
109900
109901
109902
109903
109904
109905
109906
109907
109908
109909
109910
109911
109912
109913
109914
109915
109916
109917
109918
109919
109920
109921
109922
109923
109924
109925
109926
109927
109928
109929
109930
109931
109932
109933


109934
109935

109936
109937
109938
109939
109940
109941
109942
109943
109944
109945
109946
109947
109948
109949
109950
......
109990
109991
109992
109993
109994
109995
109996
109997
109998
109999
110000
110001
110002
110003
110004
110005
110006
......
110018
110019
110020
110021
110022
110023
110024
110025
110026
110027
110028
110029
110030
110031
110032
110033
110034
110035
110036
110037
110038
110039
110040
110041
110042
110043
110044
110045
110046
110047
110048
110049
110050
110051
110052
110053
110054
110055
110056
110057
110058
110059
110060
110061
110062
110063
110064
110065
110066
110067
110068
110069
110070
110071
110072
110073
110074
110075
110076
110077
110078
110079
110080
110081
110082
110083
110084
110085
110086
110087
110088
110089
110090
110091
110092
110093
110094
110095
......
110128
110129
110130
110131
110132
110133
110134
110135
110136
110137
110138
110139
110140
110141
110142
110143
......
110237
110238
110239
110240
110241
110242
110243
110244
110245
110246
110247
110248
110249
110250
110251
110252
......
110276
110277
110278
110279
110280
110281
110282
110283
110284
110285
110286
110287
110288
110289
110290
110291
110292
110293
110294
110295
110296
110297
110298
110299
110300
110301
110302
110303
110304
110305
110306
110307
110308
110309
......
110319
110320
110321
110322
110323
110324
110325

110326
110327
110328
110329
110330
110331
110332
110333
110334
110335
110336
110337
110338
110339
110340
110341
110342
110343
110344
110345
110346
110347
110348
110349
110350
110351
110352
110353
110354
110355
110356
110357
......
110364
110365
110366
110367
110368
110369
110370
110371

110372
110373
110374
110375
110376
110377
110378
110379
110380
110381
110382
110383
110384
110385
110386
110387
110388
110389
110390
110391
110392
110393
110394
110395
110396
110397
110398
110399
110400
110401
110402
110403
110404
110405
110406
110407
110408
110409
110410
110411
110412
110413
110414
110415
110416
110417
110418
110419
110420
110421
110422
110423
110424
110425
110426
110427
110428
110429
110430
110431
110432
110433
110434
110435
110436
110437
110438
110439
110440
110441
110442
110443
110444
110445
110446
110447
110448
110449
110450
110451
110452
110453
110454
110455
110456
110457
110458
110459
110460
110461
110462
110463



110464
110465
110466
110467
110468
110469
110470
110471
110472
110473
110474
110475
110476
110477
110478
110479
110480
110481
110482
110483
110484
110485
110486
110487
110488
110489
110490
110491
110492
110493
110494
110495
110496
110497
110498
110499
110500
110501
110502
110503
110504
110505
110506
110507
110508
110509
110510
110511
110512
110513
110514
110515
110516
110517
110518
110519
110520
110521
110522
110523
110524
110525
110526
110527
110528
110529
110530
110531
110532
110533
110534
110535
110536
110537
110538
110539
110540
110541
110542
110543
110544
110545
110546
110547
110548
110549
110550
110551
110552
110553
110554
110555
110556
110557
110558
110559
110560
110561
110562
110563
110564
110565
110566
110567
110568
110569
110570
110571
110572
110573
110574
110575
110576
110577
110578
110579
110580
110581
110582
110583
110584
110585
110586
110587
110588
110589
110590
110591
110592
110593
110594
110595
110596
110597
110598
110599
110600
110601
110602
110603
110604
110605
110606
110607
110608
110609
110610
110611
110612
110613
110614
110615
110616
110617
110618
110619
110620
110621
110622
110623
110624
110625
110626
110627
110628
110629
110630
110631
110632
110633
110634
110635
110636
110637
110638
110639
110640
110641
110642
110643
110644
110645
110646
110647
110648
110649
110650
110651
110652
110653
110654
110655
110656
110657
110658
110659
110660
110661
110662
110663
110664
110665
110666
110667
110668
110669
110670
110671
110672
110673
110674
110675
110676
110677
110678
110679
110680
110681
110682
110683
110684
110685
110686
110687
110688
110689
110690
110691
110692
110693
110694
110695
110696
110697
110698
110699
110700
110701
110702
110703
110704
110705
110706
110707
110708
110709
110710
110711
110712
110713
110714
110715
110716
110717
110718
110719
110720
110721
110722
110723
110724
110725
110726
110727
110728
110729
110730
110731
110732
110733
110734
110735
110736
110737
110738
110739
110740
110741
110742
110743
110744
110745
110746
110747
110748
110749
110750
......
110757
110758
110759
110760
110761
110762
110763
110764
110765
110766
110767
110768
110769
110770
110771
110772
110773
110774
110775
110776
110777
110778
110779
110780
110781
110782
110783
110784
110785
110786
110787
110788
110789
110790
110791
110792
110793
110794
110795
110796
110797
110798
110799
110800
110801
110802
110803
110804
110805
110806
110807
110808
110809
110810
......
110811
110812
110813
110814
110815
110816
110817
110818
110819
110820
110821
110822
110823
110824
110825
110826
110827
110828
110829
110830
110831
110832
110833
110834
110835
110836
110837
110838
110839
110840
110841
110842
110843
110844
110845
110846
110847
110848
110849
110850
110851
110852
110853
110854
110855
110856
110857
110858
110859
110860
110861
110862
110863
110864
110865
110866
110867
110868
110869
110870
110871
110872
110873
110874
110875
110876
110877
110878
110879
110880
110881
110882
110883
110884
110885
110886
110887
110888
110889
110890
110891
110892
110893
110894
110895
110896
110897
110898
110899
110900
110901
110902
110903
110904
110905
110906
110907
110908
110909
110910
110911
110912
110913
110914
110915
110916
110917
110918
110919
110920
110921
110922
110923
110924
110925
110926
110927
110928
110929
110930
110931
110932
110933
110934
110935
110936
110937
110938
110939
110940
110941
110942
110943
110944
110945
......
110946
110947
110948
110949
110950
110951
110952
110953
110954
110955
110956
110957
110958
110959
110960
......
110973
110974
110975
110976
110977
110978
110979
110980
110981
110982
110983
110984
110985
110986
110987
110988
110989
110990
110991
110992
110993
110994
110995
110996
110997
110998
110999
111000
111001
......
111002
111003
111004
111005
111006
111007
111008
111009
111010
111011
111012
111013
111014
111015
111016
......
111018
111019
111020
111021
111022
111023
111024
111025
111026
111027
111028
111029
111030
111031
111032
111033
111034
111035
111036
111037
111038
111039
111040
111041
111042
111043
111044
111045
111046
111047
111048
111049
111050
111051
111052
111053
111054
111055
111056
111057
111058
111059
111060
111061
111062
111063
111064
111065
111066
111067
111068
111069
111070
111071
111072
111073
111074
111075
111076
111077
111078
111079
111080
111081
111082
111083
111084
111085
111086
111087
111088
111089
111090
111091
111092
111093
111094
111095
111096
111097
111098
111099
111100
111101
111102
111103
111104
111105
111106
111107
111108
111109
111110
111111
111112
111113
111114
111115
111116
111117
111118
111119
111120
111121
111122
111123
111124
111125
111126
111127
111128
111129
111130
111131
111132
111133
111134
111135
111136
111137
111138
111139
111140
111141
111142
111143
111144
111145
111146
111147
111148
111149
111150
111151
111152
111153
111154
111155
111156
111157
111158
111159
111160
111161
111162
111163
111164
111165
111166
111167
111168
111169
111170
111171
111172
111173
111174
111175
111176
111177
111178
111179
111180
111181
111182
111183
111184
111185
111186
111187
111188
111189
111190
111191
111192
111193
111194
111195
111196
111197
111198
111199
111200
111201
111202
111203
111204
111205
111206
111207
111208
111209
111210
111211
111212
111213
111214
111215
111216
111217
111218
111219
111220
111221
111222
111223
111224
111225
111226
111227
111228
111229
111230
111231
111232
111233
111234
111235
111236
111237
111238
111239
111240
111241
111242
111243
111244
111245
111246
111247
111248
111249
111250
111251
111252
111253
111254
111255
111256
111257
111258
111259
111260
111261
111262
111263
111264
111265
111266
111267
111268
111269
111270
111271
111272
111273
111274
111275
111276
111277
111278
111279
111280
111281
111282
111283
111284
111285
111286
111287
111288
111289
111290
111291
111292
111293
111294
111295
111296
111297
111298
111299
111300
111301
111302
111303
111304
111305
111306
111307
111308
111309
111310
111311
111312
111313
111314
111315
111316
111317
111318
......
111324
111325
111326
111327
111328
111329
111330
111331
111332
111333

111334
111335
111336
111337
111338
111339
111340
111341
111342
111343
111344
111345
111346
111347
111348
111349
111350
111351
111352
111353
111354
111355
......
112851
112852
112853
112854
112855
112856
112857









112858
112859
112860
112861
112862
112863
112864
......
113049
113050
113051
113052
113053
113054
113055












113056
113057
113058
113059
113060
113061
113062
......
113496
113497
113498
113499
113500
113501
113502
113503
113504
113505

113506
113507
113508
























113509





113510







113511
113512
113513
113514
113515
113516
113517
113518
113519
113520
113521
113522
113523
113524
113525
113526
113527
113528
113529
113530
113531
113532


113533
113534

113535
113536
113537
113538
113539
113540
113541
113542

113543
113544

































113545
113546
113547
113548





113549
113550
113551
113552

113553
113554
113555
113556
113557
113558
113559
113560
113561
113562
113563









113564
113565
113566
113567
113568
113569
113570
113571
113572
113573
113574
113575
113576
113577
113578
......
113622
113623
113624
113625
113626
113627
113628
113629
113630
113631
113632
113633
113634
113635
113636
......
113651
113652
113653
113654
113655
113656
113657
113658
113659
113660
113661
113662
113663
113664
113665
......
114789
114790
114791
114792
114793
114794
114795

114796
114797
114798
114799

114800
114801
114802
114803
114804
114805
114806
......
114813
114814
114815
114816
114817
114818
114819
114820
114821
114822
114823
114824
114825
114826
114827
......
114832
114833
114834
114835
114836
114837
114838

114839
114840
114841
114842
114843
114844
114845
......
117271
117272
117273
117274
117275
117276
117277
117278
117279
117280
117281
117282







117283
117284
117285
117286
117287
117288
117289
......
120545
120546
120547
120548
120549
120550
120551



120552
120553
120554
120555
120556
120557
120558
......
120560
120561
120562
120563
120564
120565
120566



120567
120568
120569
120570
120571




120572
120573
120574
120575
120576
120577
120578
......
120589
120590
120591
120592
120593
120594
120595




120596
120597
120598
120599
120600
120601
120602
......
120936
120937
120938
120939
120940
120941
120942
120943
120944
120945
120946
120947
120948
120949
120950
......
120982
120983
120984
120985
120986
120987
120988



































120989
120990
120991
120992
120993
120994
120995
......
122138
122139
122140
122141
122142
122143
122144
122145
122146
122147
122148

122149
122150
122151
122152
122153

122154



122155
122156
122157
122158
122159
122160
122161
122162
122163




































122164
























122165
122166
122167
122168
122169
122170
122171
122172
122173
122174
122175
122176
122177
122178

122179
122180
122181
122182
122183
122184
122185
......
124954
124955
124956
124957
124958
124959
124960
124961
124962
124963
124964
124965
124966
124967
124968
124969
124970
124971
......
124994
124995
124996
124997
124998
124999
125000
125001
125002
125003
125004
125005
125006
125007

125008
125009
125010
125011



125012
125013
125014
125015
125016
125017
125018
125019
125020
125021
125022
125023
125024
125025
125026
125027
125028
125029
125030
125031
125032
125033
125034




125035
125036
125037
125038
125039
125040
125041
125042
......
125212
125213
125214
125215
125216
125217
125218
125219
125220
125221
125222
125223
125224
125225
125226
125227
125228
125229
......
125606
125607
125608
125609
125610
125611
125612

125613
125614
125615
125616
125617
125618
125619
125620
......
125640
125641
125642
125643
125644
125645
125646
125647
125648
125649
125650
125651
125652
125653
125654
......
127051
127052
127053
127054
127055
127056
127057
127058
127059
127060
127061
127062
127063
127064
127065

127066
127067
127068
127069
127070
127071
127072
......
128644
128645
128646
128647
128648
128649
128650
128651





128652
128653
128654
128655
128656
128657
128658
......
131218
131219
131220
131221
131222
131223
131224

131225
131226
131227
131228

131229
131230
131231
131232
131233
131234
131235
131236
131237
131238

131239

131240
131241
131242
131243
131244
131245
131246
131247
131248
131249
......
131628
131629
131630
131631
131632
131633
131634

131635
131636
131637
131638
131639
131640
131641
131642
131643
131644
131645
131646
131647
131648
131649
131650
131651
131652
131653
131654
131655
131656
......
131803
131804
131805
131806
131807
131808
131809

131810
131811

131812
131813
131814
131815
131816
131817
131818
......
132156
132157
132158
132159
132160
132161
132162

132163
132164
132165
132166
132167
132168
132169
132170
132171
132172
132173
132174
132175
132176
132177
132178
132179
132180
132181
132182
132183
132184
132185
132186
......
132360
132361
132362
132363
132364
132365
132366



























































































































































































































































































































































































































































































































































































































































































































































































132367
132368
132369
132370
132371
132372
132373
......
135099
135100
135101
135102
135103
135104
135105






























135106
135107
135108
135109
135110
135111
135112
......
135136
135137
135138
135139
135140
135141
135142
135143
135144
135145
135146
135147
135148
135149
135150
135151
......
136390
136391
136392
136393
136394
136395
136396
136397
136398
136399
136400
136401
136402
136403
136404
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.7.12.  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
................................................................................

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API

**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
**
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
** assert() macro is enabled, each call into the Win32 native heap subsystem
** will cause HeapValidate to be called.  If heap validation should fail, an
** assertion will be triggered.
**
** (Historical note:  There used to be several other options, but we've
** pared it down to just these three.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1



# error "At most one of the following compile-time configuration options\

 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG"

#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0



# define SQLITE_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/
................................................................................
** The TCL headers are only needed when compiling the TCL bindings.
*/
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.



** Setting NDEBUG makes the code smaller and run faster.  So the following
** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1


** option is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
*/
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
# define NDEBUG 1



#endif

/*
** The testcase() macro is used to aid in coverage testing.  When 
** doing coverage testing, the condition inside the argument to
** testcase() must be evaluated both true and false in order to
** get full branch coverage.  The testcase() macro is inserted
................................................................................
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.12"
#define SQLITE_VERSION_NUMBER 3007012
#define SQLITE_SOURCE_ID      "2012-04-17 09:09:33 8e2363ad76446e863d03ead91fd621e59d5cb495"

/*
** 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
................................................................................
** CAPI3REF: Database Connection Handle
** KEYWORDS: {database connection} {database connections}
**
** Each open SQLite database is represented by a pointer to an instance of
** the opaque structure named "sqlite3".  It is useful to think of an sqlite3
** pointer as an object.  The [sqlite3_open()], [sqlite3_open16()], and
** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]

** is its destructor.  There are many other interfaces (such as
** [sqlite3_prepare_v2()], [sqlite3_create_function()], and
** [sqlite3_busy_timeout()] to name but three) that are methods on an
** sqlite3 object.
*/
typedef struct sqlite3 sqlite3;

/*
................................................................................
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite3_int64
#endif

/*
** CAPI3REF: Closing A Database Connection
**

** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
** successfully destroyed and all associated resources are deallocated.

**











** Applications must [sqlite3_finalize | finalize] all [prepared statements]
** and [sqlite3_blob_close | close] all [BLOB handles] associated with

** the [sqlite3] object prior to attempting to close the object.  ^If
** sqlite3_close() is called on a [database connection] that still has
** outstanding [prepared statements] or [BLOB handles], then it returns
** SQLITE_BUSY.



**
** ^If [sqlite3_close()] is invoked while a transaction is open,
** the transaction is automatically rolled back.
**
** The C parameter to [sqlite3_close(C)] must be either a NULL

** pointer or an [sqlite3] object pointer obtained
** from [sqlite3_open()], [sqlite3_open16()], or
** [sqlite3_open_v2()], and not previously closed.
** ^Calling sqlite3_close() with a NULL pointer argument is a 
** harmless no-op.
*/
SQLITE_API int sqlite3_close(sqlite3 *);


/*
** The type for a callback function.
** This is legacy and deprecated.  It is included for historical
** compatibility and is not documented.
*/
typedef int (*sqlite3_callback)(void*,int,char**, char**);
................................................................................
#define SQLITE_IOERR_SHMSIZE           (SQLITE_IOERR | (19<<8))
#define SQLITE_IOERR_SHMLOCK           (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP            (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK              (SQLITE_IOERR | (22<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))

#define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
#define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))

/*
** CAPI3REF: Flags For File Open Operations
................................................................................
#define SQLITE_OPEN_READONLY         0x00000001  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE        0x00000002  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_CREATE           0x00000004  /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_DELETEONCLOSE    0x00000008  /* VFS only */
#define SQLITE_OPEN_EXCLUSIVE        0x00000010  /* VFS only */
#define SQLITE_OPEN_AUTOPROXY        0x00000020  /* VFS only */
#define SQLITE_OPEN_URI              0x00000040  /* Ok for sqlite3_open_v2() */

#define SQLITE_OPEN_MAIN_DB          0x00000100  /* VFS only */
#define SQLITE_OPEN_TEMP_DB          0x00000200  /* VFS only */
#define SQLITE_OPEN_TRANSIENT_DB     0x00000400  /* VFS only */
#define SQLITE_OPEN_MAIN_JOURNAL     0x00000800  /* VFS only */
#define SQLITE_OPEN_TEMP_JOURNAL     0x00001000  /* VFS only */
#define SQLITE_OPEN_SUBJOURNAL       0x00002000  /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL   0x00004000  /* VFS only */
................................................................................
** integer is the delay.  If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
** interrogated.  The zDbName parameter is ignored.
**
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write AHead Log] setting.  By default, the auxiliary
** write ahead log and shared memory files used for transaction control
** are automatically deleted when the latest connection to the database
** closes.  Setting persistent WAL mode causes those files to persist after
** close.  Persisting the files is useful when other processes that do not
** have write permission on the directory containing the database file want
** to read the database file, as the WAL and shared memory files must exist
** in order for the database to be readable.  The fourth parameter to
................................................................................
** option is used.
**
** In SQLite version 3.5.0 and 3.5.1, it was possible to define
** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
** implementation of these routines to be omitted.  That capability
** is no longer provided.  Only built-in memory allocators can be used.
**
** The Windows OS interface layer calls
** the system malloc() and free() directly when converting
** filenames between the UTF-8 encoding used by SQLite
** and whatever filename encoding is used by the particular Windows
** installation.  Memory allocation errors are detected, but
** they are reported back as [SQLITE_CANTOPEN] or
** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
**
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
** not yet been released.
**
................................................................................
**     a VFS object that provides the operating system interface that should
**     be used to access the database file on disk. ^If this option is set to
**     an empty string the default VFS object is used. ^Specifying an unknown
**     VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
**     present, then the VFS specified by the option takes precedence over
**     the value passed as the fourth parameter to sqlite3_open_v2().
**
**   <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
**     "rwc". Attempting to set it to any other value is an error)^. 

**     ^If "ro" is specified, then the database is opened for read-only 
**     access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the 
**     third argument to sqlite3_prepare_v2(). ^If the mode option is set to 
**     "rw", then the database is opened for read-write (but not create) 
**     access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had 
**     been set. ^Value "rwc" is equivalent to setting both 
**     SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is 

**     used, it is an error to specify a value for the mode parameter that is 
**     less restrictive than that specified by the flags passed as the third 
**     parameter.

**
**   <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
**     "private". ^Setting it to "shared" is equivalent to setting the
**     SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
**     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
**     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
**     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
................................................................................
** using [sqlite3_free].
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
*/
SQLITE_API char *sqlite3_temp_directory;






































/*
** CAPI3REF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
**
** ^The sqlite3_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
** respectively.  ^Autocommit mode is on by default.
................................................................................
  sqlite3*, 
  void(*)(void *,int ,char const *,char const *,sqlite3_int64),
  void*
);

/*
** CAPI3REF: Enable Or Disable Shared Pager Cache
** KEYWORDS: {shared cache}
**
** ^(This routine enables or disables the sharing of the database cache
** and schema data structures between [database connection | connections]
** to the same database. Sharing is enabled if the argument is true
** and disabled if the argument is false.)^
**
** ^Cache sharing is enabled and disabled for an entire process.
................................................................................
**
** The SQLite source code contains multiple implementations
** of these mutex routines.  An appropriate implementation
** is selected automatically at compile-time.  ^(The following
** implementations are available in the SQLite core:
**
** <ul>
** <li>   SQLITE_MUTEX_OS2
** <li>   SQLITE_MUTEX_PTHREADS
** <li>   SQLITE_MUTEX_W32
** <li>   SQLITE_MUTEX_NOOP
** </ul>)^
**
** ^The SQLITE_MUTEX_NOOP implementation is a set of routines
** that does no real locking and is appropriate for use in
** a single-threaded application.  ^The SQLITE_MUTEX_OS2,
** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations
** are appropriate for use on OS/2, Unix, and Windows.
**
** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
** implementation is included with the library. In this case the
** application must supply a custom mutex implementation using the
** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
** before calling sqlite3_initialize() or any other public sqlite3_
................................................................................
** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
** <dd>This parameter returns the number of dirty cache entries that have
** been written to disk. Specifically, the number of pages written to the
** wal file in wal mode databases, or the number of pages written to the
** database file in rollback mode databases. Any pages written as part of
** transaction rollback or database recovery operations are not included.
** If an IO or other error occurs while writing a page to disk, the effect
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined). ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED       0
#define SQLITE_DBSTATUS_CACHE_USED           1
#define SQLITE_DBSTATUS_SCHEMA_USED          2
................................................................................
SQLITE_PRIVATE   int sqlite3PagerWalFramesize(Pager *pPager);
#endif

/* Functions used to query pager state and configuration. */
SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
................................................................................
*/
#ifndef _SQLITE_OS_H_
#define _SQLITE_OS_H_

/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.  After the following block of preprocess macros,
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER 
** will defined to either 1 or 0.  One of the four will be 1.  The other 
** three will be 0.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
#   undef SQLITE_OS_UNIX
#   define SQLITE_OS_UNIX 0
#   undef SQLITE_OS_WIN
#   define SQLITE_OS_WIN 0
#   undef SQLITE_OS_OS2
#   define SQLITE_OS_OS2 0
# else
#   undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
#   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
#     define SQLITE_OS_WIN 1
#     define SQLITE_OS_UNIX 0
#     define SQLITE_OS_OS2 0
#   elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__)
#     define SQLITE_OS_WIN 0
#     define SQLITE_OS_UNIX 0
#     define SQLITE_OS_OS2 1
#   else
#     define SQLITE_OS_WIN 0
#     define SQLITE_OS_UNIX 1
#     define SQLITE_OS_OS2 0
#  endif
# else
#  define SQLITE_OS_UNIX 0
#  define SQLITE_OS_OS2 0
# endif
#else
# ifndef SQLITE_OS_WIN
#  define SQLITE_OS_WIN 0
# endif
#endif

/*
** Define the maximum size of a temporary filename
*/
#if SQLITE_OS_WIN
# include <windows.h>
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
#elif SQLITE_OS_OS2
# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY)
#  include <os2safe.h> /* has to be included before os2.h for linking to work */
# endif
# define INCL_DOSDATETIME
# define INCL_DOSFILEMGR
# define INCL_DOSERRORS
# define INCL_DOSMISC
# define INCL_DOSPROCESS
# define INCL_DOSMODULEMGR
# define INCL_DOSSEMAPHORES
# include <os2.h>
# include <uconv.h>
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif

/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for win98 or winNT
** using the _WIN32_WINNT macro as follows:
................................................................................
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif

















/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif

................................................................................
**                             mutual exclusion is provided.  But this
**                             implementation can be overridden at
**                             start-time.
**
**   SQLITE_MUTEX_PTHREADS     For multi-threaded applications on Unix.
**
**   SQLITE_MUTEX_W32          For multi-threaded applications on Win32.
**
**   SQLITE_MUTEX_OS2          For multi-threaded applications on OS/2.
*/
#if !SQLITE_THREADSAFE
# define SQLITE_MUTEX_OMIT
#endif
#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
#  if SQLITE_OS_UNIX
#    define SQLITE_MUTEX_PTHREADS
#  elif SQLITE_OS_WIN
#    define SQLITE_MUTEX_W32
#  elif SQLITE_OS_OS2
#    define SQLITE_MUTEX_OS2
#  else
#    define SQLITE_MUTEX_NOOP
#  endif
#endif

#ifdef SQLITE_MUTEX_OMIT
/*
................................................................................
** than being distinct from one another.
*/
#define SQLITE_MAGIC_OPEN     0xa029a697  /* Database is open */
#define SQLITE_MAGIC_CLOSED   0x9f3c2d33  /* Database is closed */
#define SQLITE_MAGIC_SICK     0x4b771290  /* Error and awaiting close */
#define SQLITE_MAGIC_BUSY     0xf03b7906  /* Database currently in use */
#define SQLITE_MAGIC_ERROR    0xb5357930  /* An SQLITE_MISUSE error occurred */


/*
** Each SQL function is defined by an instance of the following
** structure.  A pointer to this structure is stored in the sqlite.aFunc
** hash table.  When multiple functions have the same name, the hash table
** points to a linked list of these structures.
*/
................................................................................
** NameContext list corresponds to searching through successively outer
** subqueries looking for a match.
*/
struct NameContext {
  Parse *pParse;       /* The parser */
  SrcList *pSrcList;   /* One or more tables used to resolve names */
  ExprList *pEList;    /* Optional list of named expressions */


  int nRef;            /* Number of names resolved by this context */
  int nErr;            /* Number of errors encountered while resolving names */
  u8 allowAgg;         /* Aggregate functions allowed here */
  u8 hasAgg;           /* True if aggregates are seen */
  u8 isCheck;          /* True if resolving names in a CHECK constraint */
  AggInfo *pAggInfo;   /* Information about aggregates at this level */
  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
};









/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
** limit and nOffset to the value of the offset (or 0 if there is not
................................................................................
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);

SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);

SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
................................................................................
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);

SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
................................................................................
#  define sqlite3VtabLock(X) 
#  define sqlite3VtabUnlock(X)
#  define sqlite3VtabUnlockList(X)
#  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
#  define sqlite3GetVTable(X,Y)  ((VTable*)0)
#else
SQLITE_PRIVATE    void sqlite3VtabClear(sqlite3 *db, Table*);

SQLITE_PRIVATE    int sqlite3VtabSync(sqlite3 *db, char **);
SQLITE_PRIVATE    int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE    int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE    void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE    void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE    int sqlite3VtabSavepoint(sqlite3 *, int, int);
................................................................................
  "CASE_SENSITIVE_LIKE",
#endif
#ifdef SQLITE_CHECK_PAGES
  "CHECK_PAGES",
#endif
#ifdef SQLITE_COVERAGE_TEST
  "COVERAGE_TEST",



#endif
#ifdef SQLITE_DEBUG
  "DEBUG",
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
................................................................................
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
  return sqlite3NoopMutex();
}
#endif /* defined(SQLITE_MUTEX_NOOP) */
#endif /* !defined(SQLITE_MUTEX_OMIT) */

/************** End of mutex_noop.c ******************************************/
/************** Begin file mutex_os2.c ***************************************/
/*
** 2007 August 28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes for OS/2
*/

/*
** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
** See the mutex.h file for details.
*/
#ifdef SQLITE_MUTEX_OS2

/********************** OS/2 Mutex Implementation **********************
**
** This implementation of mutexes is built using the OS/2 API.
*/

/*
** The mutex object
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite3_mutex {
  HMTX mutex;       /* Mutex controlling the lock */
  int  id;          /* Mutex type */
#ifdef SQLITE_DEBUG
 int   trace;       /* True to trace changes */
#endif
};

#ifdef SQLITE_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
#endif

/*
** Initialize and deinitialize the mutex subsystem.
*/
static int os2MutexInit(void){ return SQLITE_OK; }
static int os2MutexEnd(void){ return SQLITE_OK; }

/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated. 
** SQLite will unwind its stack and return an error.  The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE_MUTEX_FAST
** <li>  SQLITE_MUTEX_RECURSIVE
** <li>  SQLITE_MUTEX_STATIC_MASTER
** <li>  SQLITE_MUTEX_STATIC_MEM
** <li>  SQLITE_MUTEX_STATIC_MEM2
** <li>  SQLITE_MUTEX_STATIC_PRNG
** <li>  SQLITE_MUTEX_STATIC_LRU
** <li>  SQLITE_MUTEX_STATIC_LRU2
** </ul>
**
** The first two constants cause sqlite3_mutex_alloc() to create
** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
** not want to.  But SQLite will only request a recursive mutex in
** cases where it really needs one.  If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE_MUTEX_FAST.
**
** The other allowed parameters to sqlite3_mutex_alloc() each return
** a pointer to a static preexisting mutex.  Six static mutexes are
** used by the current version of SQLite.  Future versions of SQLite
** may add additional static mutexes.  Static mutexes are for internal
** use by SQLite only.  Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
** SQLITE_MUTEX_RECURSIVE.
**
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
** returns a different mutex on every call.  But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
static sqlite3_mutex *os2MutexAlloc(int iType){
  sqlite3_mutex *p = NULL;
  switch( iType ){
    case SQLITE_MUTEX_FAST:
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){
        p->id = iType;
        if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){
          sqlite3_free( p );
          p = NULL;
        }
      }
      break;
    }
    default: {
      static volatile int isInit = 0;
      static sqlite3_mutex staticMutexes[6] = {
        SQLITE3_MUTEX_INITIALIZER,
        SQLITE3_MUTEX_INITIALIZER,
        SQLITE3_MUTEX_INITIALIZER,
        SQLITE3_MUTEX_INITIALIZER,
        SQLITE3_MUTEX_INITIALIZER,
        SQLITE3_MUTEX_INITIALIZER,
      };
      if ( !isInit ){
        APIRET rc;
        PTIB ptib;
        PPIB ppib;
        HMTX mutex;
        char name[32];
        DosGetInfoBlocks( &ptib, &ppib );
        sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x",
                          ppib->pib_ulpid );
        while( !isInit ){
          mutex = 0;
          rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
          if( rc == NO_ERROR ){
            unsigned int i;
            if( !isInit ){
              for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
                DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
              }
              isInit = 1;
            }
            DosCloseMutexSem( mutex );
          }else if( rc == ERROR_DUPLICATE_NAME ){
            DosSleep( 1 );
          }else{
            return p;
          }
        }
      }
      assert( iType-2 >= 0 );
      assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
      p = &staticMutexes[iType-2];
      p->id = iType;
      break;
    }
  }
  return p;
}


/*
** This routine deallocates a previously allocated mutex.
** SQLite is careful to deallocate every mutex that it allocates.
*/
static void os2MutexFree(sqlite3_mutex *p){
#ifdef SQLITE_DEBUG
  TID tid;
  PID pid;
  ULONG ulCount;
  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  assert( ulCount==0 );
  assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
  DosCloseMutexSem( p->mutex );
  sqlite3_free( p );
}

#ifdef SQLITE_DEBUG
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
static int os2MutexHeld(sqlite3_mutex *p){
  TID tid;
  PID pid;
  ULONG ulCount;
  PTIB ptib;
  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
    return 0;
  DosGetInfoBlocks(&ptib, NULL);
  return tid==ptib->tib_ptib2->tib2_ultid;
}
static int os2MutexNotheld(sqlite3_mutex *p){
  TID tid;
  PID pid;
  ULONG ulCount;
  PTIB ptib;
  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  if( ulCount==0 )
    return 1;
  DosGetInfoBlocks(&ptib, NULL);
  return tid!=ptib->tib_ptib2->tib2_ultid;
}
static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
  TID   tid;
  PID   pid;
  ULONG ulCount;
  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
  printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
}
#endif

/*
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
** to enter a mutex.  If another thread is already within the mutex,
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
** SQLITE_BUSY.  The sqlite3_mutex_try() interface returns SQLITE_OK
** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
** be entered multiple times by the same thread.  In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void os2MutexEnter(sqlite3_mutex *p){
  assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
  DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
#ifdef SQLITE_DEBUG
  if( p->trace ) os2MutexTrace(p, "enter");
#endif
}
static int os2MutexTry(sqlite3_mutex *p){
  int rc = SQLITE_BUSY;
  assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
  if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
    rc = SQLITE_OK;
#ifdef SQLITE_DEBUG
    if( p->trace ) os2MutexTrace(p, "try");
#endif
  }
  return rc;
}

/*
** The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.  The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated.  SQLite will never do either.
*/
static void os2MutexLeave(sqlite3_mutex *p){
  assert( os2MutexHeld(p) );
  DosReleaseMutexSem(p->mutex);
#ifdef SQLITE_DEBUG
  if( p->trace ) os2MutexTrace(p, "leave");
#endif
}

SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
  static const sqlite3_mutex_methods sMutex = {
    os2MutexInit,
    os2MutexEnd,
    os2MutexAlloc,
    os2MutexFree,
    os2MutexEnter,
    os2MutexTry,
    os2MutexLeave,
#ifdef SQLITE_DEBUG
    os2MutexHeld,
    os2MutexNotheld
#else
    0,
    0
#endif
  };

  return &sMutex;
}
#endif /* SQLITE_MUTEX_OS2 */

/************** End of mutex_os2.c *******************************************/
/************** Begin file mutex_unix.c **************************************/
/*
** 2007 August 28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
................................................................................
** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
** which is only available if your application was compiled with 
** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
** this out as well.
*/
#if 0
#if SQLITE_OS_WINCE
# define mutexIsNT()  (1)
#else
  static int mutexIsNT(void){
    static int osType = 0;
    if( osType==0 ){
      OSVERSIONINFO sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
................................................................................
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite3_initialize and sqlite3_shutdown()
** processing, the "interlocked" magic is probably not
** strictly necessary.
*/
static long winMutex_lock = 0;



static int winMutexInit(void){ 
  /* The first to increment to 1 does actual initialization */
  if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
    int i;
    for(i=0; i<ArraySize(winMutex_staticMutexes); i++){



      InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);

    }
    winMutex_isInit = 1;
  }else{
    /* Someone else is in the process of initing the static mutexes */
    while( !winMutex_isInit ){
      Sleep(1);
    }
  }
  return SQLITE_OK; 
}

static int winMutexEnd(void){ 
  /* The first to decrement to 0 does actual shutdown 
................................................................................
    case SQLITE_MUTEX_FAST:
    case SQLITE_MUTEX_RECURSIVE: {
      p = sqlite3MallocZero( sizeof(*p) );
      if( p ){  
#ifdef SQLITE_DEBUG
        p->id = iType;
#endif



        InitializeCriticalSection(&p->mutex);

      }
      break;
    }
    default: {
      assert( winMutex_isInit==1 );
      assert( iType-2 >= 0 );
      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
................................................................................
  if( db ){
    if( db->pnBytesFreed ){
      *db->pnBytesFreed += sqlite3DbMallocSize(db, p);
      return;
    }
    if( isLookaside(db, p) ){
      LookasideSlot *pBuf = (LookasideSlot*)p;




      pBuf->pNext = db->lookaside.pFree;
      db->lookaside.pFree = pBuf;
      db->lookaside.nOut--;
      return;
    }
  }
  assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
................................................................................
** The counter *cnt is incremented each time.  After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
  int digit;
  LONGDOUBLE_TYPE d;
  if( (*cnt)++ >= 16 ) return '0';

  digit = (int)*val;
  d = digit;
  digit += '0';
  *val = (*val - d)*10.0;
  return (char)digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
................................................................................
        exp = 0;
        if( sqlite3IsNaN((double)realvalue) ){
          bufpt = "NaN";
          length = 3;
          break;
        }
        if( realvalue>0.0 ){
          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }



          while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
          while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
          if( exp>350 ){
            if( prefix=='-' ){
              bufpt = "-Inf";
            }else if( prefix=='+' ){
              bufpt = "+Inf";
................................................................................
          if( exp<-4 || exp>precision ){
            xtype = etEXP;
          }else{
            precision = precision - exp;
            xtype = etFLOAT;
          }
        }else{
          flag_rtz = 0;
        }
        if( xtype==etEXP ){
          e2 = 0;
        }else{
          e2 = exp;
        }
        if( e2+precision+width > etBUFSIZE - 15 ){
................................................................................
          bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
          if( bufpt==0 ){
            pAccum->mallocFailed = 1;
            return;
          }
        }
        zOut = bufpt;
        nsd = 0;
        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
        /* The sign in front of the number */
        if( prefix ){
          *(bufpt++) = prefix;
        }
        /* Digits prior to the decimal point */
        if( e2<0 ){
................................................................................

    /* adjust the sign of significand */
    s = sign<0 ? -s : s;

    /* if exponent, scale significand as appropriate
    ** and store in result. */
    if( e ){
      double scale = 1.0;
      /* attempt to handle extremely small/large numbers better */
      if( e>307 && e<342 ){
        while( e%308 ) { scale *= 1.0e+1; e -= 1; }
        if( esign<0 ){
          result = s / scale;
          result /= 1.0e+308;
        }else{
................................................................................
     /* 150 */ "Explain",
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_os2.c ******************************************/
/*
** 2006 Feb 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains code that is specific to OS/2.
*/


#if SQLITE_OS_OS2

/*
** A Note About Memory Allocation:
**
** This driver uses malloc()/free() directly rather than going through
** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers
** are designed for use on embedded systems where memory is scarce and
** malloc failures happen frequently.  OS/2 does not typically run on
** embedded systems, and when it does the developers normally have bigger
** problems to worry about than running out of memory.  So there is not
** a compelling need to use the wrappers.
**
** But there is a good reason to not use the wrappers.  If we use the
** wrappers then we will get simulated malloc() failures within this
** driver.  And that causes all kinds of problems for our tests.  We
** could enhance SQLite to deal with simulated malloc failures within
** the OS driver, but the code to deal with those failure would not
** be exercised on Linux (which does not need to malloc() in the driver)
** and so we would have difficulty writing coverage tests for that
** code.  Better to leave the code out, we think.
**
** The point of this discussion is as follows:  When creating a new
** OS layer for an embedded system, if you use this file as an example,
** avoid the use of malloc()/free().  Those routines work ok on OS/2
** desktops but not so well in embedded systems.
*/

/*
** Macros used to determine whether or not to use threads.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE
# define SQLITE_OS2_THREADS 1
#endif

/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_os2.c ****************/
/************** Begin file os_common.h ***************************************/
/*
** 2004 May 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains macros and a little bit of code that is common to
** all of the platform-specific files (os_*.c) and is #included into those
** files.
**
** This file should be #included by the os_*.c files only.  It is not a
** general purpose header file.
*/
#ifndef _OS_COMMON_H_
#define _OS_COMMON_H_

/*
** At least two bugs have slipped in because we changed the MEMORY_DEBUG
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch.  The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
#endif

#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
# ifndef SQLITE_DEBUG_OS_TRACE
#   define SQLITE_DEBUG_OS_TRACE 0
# endif
  int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
# define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
#else
# define OSTRACE(X)
#endif

/*
** Macros for performance tracing.  Normally turned off.  Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE

/* 
** hwtime.h contains inline assembler code for implementing 
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of os_common.h ****************/
/************** Begin file hwtime.h ******************************************/
/*
** 2008 May 27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_

/*
** The following routine only works on pentium-class (or newer) processors.
** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value.  This can be used for high-res
** profiling.
*/
#if (defined(__GNUC__) || defined(_MSC_VER)) && \
      (defined(i386) || defined(__i386__) || defined(_M_IX86))

  #if defined(__GNUC__)

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
     unsigned int lo, hi;
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
     return (sqlite_uint64)hi << 32 | lo;
  }

  #elif defined(_MSC_VER)

  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
     __asm {
        rdtsc
        ret       ; return value at EDX:EAX
     }
  }

  #endif

#elif (defined(__GNUC__) && defined(__x86_64__))

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
      unsigned long val;
      __asm__ __volatile__ ("rdtsc" : "=A" (val));
      return val;
  }
 
#elif (defined(__GNUC__) && defined(__ppc__))

  __inline__ sqlite_uint64 sqlite3Hwtime(void){
      unsigned long long retval;
      unsigned long junk;
      __asm__ __volatile__ ("\n\
          1:      mftbu   %1\n\
                  mftb    %L0\n\
                  mftbu   %0\n\
                  cmpw    %0,%1\n\
                  bne     1b"
                  : "=r" (retval), "=r" (junk));
      return retval;
  }

#else

  #error Need implementation of sqlite3Hwtime() for your platform.

  /*
  ** To compile without implementing sqlite3Hwtime() for your platform,
  ** you can remove the above #error and use the following
  ** stub function.  You will lose timing support for many
  ** of the debugging and testing utilities, but it should at
  ** least compile and run.
  */
SQLITE_PRIVATE   sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }

#endif

#endif /* !defined(_HWTIME_H_) */

/************** End of hwtime.h **********************************************/
/************** Continuing where we left off in os_common.h ******************/

static sqlite_uint64 g_start;
static sqlite_uint64 g_elapsed;
#define TIMER_START       g_start=sqlite3Hwtime()
#define TIMER_END         g_elapsed=sqlite3Hwtime()-g_start
#define TIMER_ELAPSED     g_elapsed
#else
#define TIMER_START
#define TIMER_END
#define TIMER_ELAPSED     ((sqlite_uint64)0)
#endif

/*
** If we compile with the SQLITE_TEST macro set, then the following block
** of code will give us the ability to simulate a disk I/O error.  This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_io_error_hit = 0;            /* Total number of I/O Errors */
SQLITE_API int sqlite3_io_error_hardhit = 0;        /* Number of non-benign errors */
SQLITE_API int sqlite3_io_error_pending = 0;        /* Count down to first I/O error */
SQLITE_API int sqlite3_io_error_persist = 0;        /* True if I/O errors persist */
SQLITE_API int sqlite3_io_error_benign = 0;         /* True if errors are benign */
SQLITE_API int sqlite3_diskfull_pending = 0;
SQLITE_API int sqlite3_diskfull = 0;
#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
#define SimulateIOError(CODE)  \
  if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
       || sqlite3_io_error_pending-- == 1 )  \
              { local_ioerr(); CODE; }
static void local_ioerr(){
  IOTRACE(("IOERR\n"));
  sqlite3_io_error_hit++;
  if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
}
#define SimulateDiskfullError(CODE) \
   if( sqlite3_diskfull_pending ){ \
     if( sqlite3_diskfull_pending == 1 ){ \
       local_ioerr(); \
       sqlite3_diskfull = 1; \
       sqlite3_io_error_hit = 1; \
       CODE; \
     }else{ \
       sqlite3_diskfull_pending--; \
     } \
   }
#else
#define SimulateIOErrorBenign(X)
#define SimulateIOError(A)
#define SimulateDiskfullError(A)
#endif

/*
** When testing, keep a count of the number of open files.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_open_file_count = 0;
#define OpenCounter(X)  sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif

#endif /* !defined(_OS_COMMON_H_) */

/************** End of os_common.h *******************************************/
/************** Continuing where we left off in os_os2.c *********************/

/* Forward references */
typedef struct os2File os2File;         /* The file structure */
typedef struct os2ShmNode os2ShmNode;   /* A shared descritive memory node */
typedef struct os2ShmLink os2ShmLink;   /* A connection to shared-memory */

/*
** The os2File structure is subclass of sqlite3_file specific for the OS/2
** protability layer.
*/
struct os2File {
  const sqlite3_io_methods *pMethod;  /* Always the first entry */
  HFILE h;                  /* Handle for accessing the file */
  int flags;                /* Flags provided to os2Open() */
  int locktype;             /* Type of lock currently held on this file */
  int szChunk;              /* Chunk size configured by FCNTL_CHUNK_SIZE */
  char *zFullPathCp;        /* Full path name of this file */
  os2ShmLink *pShmLink;     /* Instance of shared memory on this file */
};

#define LOCK_TIMEOUT 10L /* the default locking timeout */

/*
** Missing from some versions of the OS/2 toolkit -
** used to allocate from high memory if possible
*/
#ifndef OBJ_ANY
# define OBJ_ANY 0x00000400
#endif

/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
******************************************************************************/

/*
** Close a file.
*/
static int os2Close( sqlite3_file *id ){
  APIRET rc;
  os2File *pFile = (os2File*)id;

  assert( id!=0 );
  OSTRACE(( "CLOSE %d (%s)\n", pFile->h, pFile->zFullPathCp ));

  rc = DosClose( pFile->h );

  if( pFile->flags & SQLITE_OPEN_DELETEONCLOSE )
    DosForceDelete( (PSZ)pFile->zFullPathCp );

  free( pFile->zFullPathCp );
  pFile->zFullPathCp = NULL;
  pFile->locktype = NO_LOCK;
  pFile->h = (HFILE)-1;
  pFile->flags = 0;

  OpenCounter( -1 );
  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}

/*
** Read data from a file into a buffer.  Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes
** wrong.
*/
static int os2Read(
  sqlite3_file *id,               /* File to read from */
  void *pBuf,                     /* Write content into this buffer */
  int amt,                        /* Number of bytes to read */
  sqlite3_int64 offset            /* Begin reading at this offset */
){
  ULONG fileLocation = 0L;
  ULONG got;
  os2File *pFile = (os2File*)id;
  assert( id!=0 );
  SimulateIOError( return SQLITE_IOERR_READ );
  OSTRACE(( "READ %d lock=%d\n", pFile->h, pFile->locktype ));
  if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
    return SQLITE_IOERR;
  }
  if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){
    return SQLITE_IOERR_READ;
  }
  if( got == (ULONG)amt )
    return SQLITE_OK;
  else {
    /* Unread portions of the input buffer must be zero-filled */
    memset(&((char*)pBuf)[got], 0, amt-got);
    return SQLITE_IOERR_SHORT_READ;
  }
}

/*
** Write data from a buffer into a file.  Return SQLITE_OK on success
** or some other error code on failure.
*/
static int os2Write(
  sqlite3_file *id,               /* File to write into */
  const void *pBuf,               /* The bytes to be written */
  int amt,                        /* Number of bytes to write */
  sqlite3_int64 offset            /* Offset into the file to begin writing at */
){
  ULONG fileLocation = 0L;
  APIRET rc = NO_ERROR;
  ULONG wrote;
  os2File *pFile = (os2File*)id;
  assert( id!=0 );
  SimulateIOError( return SQLITE_IOERR_WRITE );
  SimulateDiskfullError( return SQLITE_FULL );
  OSTRACE(( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ));
  if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
    return SQLITE_IOERR;
  }
  assert( amt>0 );
  while( amt > 0 &&
         ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR &&
         wrote > 0
  ){
    amt -= wrote;
    pBuf = &((char*)pBuf)[wrote];
  }

  return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
static int os2Truncate( sqlite3_file *id, i64 nByte ){
  APIRET rc;
  os2File *pFile = (os2File*)id;
  assert( id!=0 );
  OSTRACE(( "TRUNCATE %d %lld\n", pFile->h, nByte ));
  SimulateIOError( return SQLITE_IOERR_TRUNCATE );

  /* If the user has configured a chunk-size for this file, truncate the
  ** file so that it consists of an integer number of chunks (i.e. the
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
  if( pFile->szChunk ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }
  
  rc = DosSetFileSize( pFile->h, nByte );
  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
}

#ifdef SQLITE_TEST
/*
** Count the number of fullsyncs and normal syncs.  This is used to test
** that syncs and fullsyncs are occuring at the right times.
*/
SQLITE_API int sqlite3_sync_count = 0;
SQLITE_API int sqlite3_fullsync_count = 0;
#endif

/*
** Make sure all writes to a particular file are committed to disk.
*/
static int os2Sync( sqlite3_file *id, int flags ){
  os2File *pFile = (os2File*)id;
  OSTRACE(( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ));
#ifdef SQLITE_TEST
  if( flags & SQLITE_SYNC_FULL){
    sqlite3_fullsync_count++;
  }
  sqlite3_sync_count++;
#endif
  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  ** no-op
  */
#ifdef SQLITE_NO_SYNC
  UNUSED_PARAMETER(pFile);
  return SQLITE_OK;
#else
  return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
#endif
}

/*
** Determine the current size of a file in bytes
*/
static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){
  APIRET rc = NO_ERROR;
  FILESTATUS3 fsts3FileInfo;
  memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
  assert( id!=0 );
  SimulateIOError( return SQLITE_IOERR_FSTAT );
  rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
  if( rc == NO_ERROR ){
    *pSize = fsts3FileInfo.cbFile;
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR_FSTAT;
  }
}

/*
** Acquire a reader lock.
*/
static int getReadLock( os2File *pFile ){
  FILELOCK  LockArea,
            UnlockArea;
  APIRET res;
  memset(&LockArea, 0, sizeof(LockArea));
  memset(&UnlockArea, 0, sizeof(UnlockArea));
  LockArea.lOffset = SHARED_FIRST;
  LockArea.lRange = SHARED_SIZE;
  UnlockArea.lOffset = 0L;
  UnlockArea.lRange = 0L;
  res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
  OSTRACE(( "GETREADLOCK %d res=%d\n", pFile->h, res ));
  return res;
}

/*
** Undo a readlock
*/
static int unlockReadLock( os2File *id ){
  FILELOCK  LockArea,
            UnlockArea;
  APIRET res;
  memset(&LockArea, 0, sizeof(LockArea));
  memset(&UnlockArea, 0, sizeof(UnlockArea));
  LockArea.lOffset = 0L;
  LockArea.lRange = 0L;
  UnlockArea.lOffset = SHARED_FIRST;
  UnlockArea.lRange = SHARED_SIZE;
  res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
  OSTRACE(( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ));
  return res;
}

/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
**     (1) SHARED_LOCK
**     (2) RESERVED_LOCK
**     (3) PENDING_LOCK
**     (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between.  The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal.  The following chart shows the allowed
** transitions and the inserted intermediate states:
**
**    UNLOCKED -> SHARED
**    SHARED -> RESERVED
**    SHARED -> (PENDING) -> EXCLUSIVE
**    RESERVED -> (PENDING) -> EXCLUSIVE
**    PENDING -> EXCLUSIVE
**
** This routine will only increase a lock.  The os2Unlock() routine
** erases all locks at once and returns us immediately to locking level 0.
** It is not possible to lower the locking level one step at a time.  You
** must go straight to locking level 0.
*/
static int os2Lock( sqlite3_file *id, int locktype ){
  int rc = SQLITE_OK;       /* Return code from subroutines */
  APIRET res = NO_ERROR;    /* Result of an OS/2 lock call */
  int newLocktype;       /* Set pFile->locktype to this value before exiting */
  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
  FILELOCK  LockArea,
            UnlockArea;
  os2File *pFile = (os2File*)id;
  memset(&LockArea, 0, sizeof(LockArea));
  memset(&UnlockArea, 0, sizeof(UnlockArea));
  assert( pFile!=0 );
  OSTRACE(( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ));

  /* If there is already a lock of this type or more restrictive on the
  ** os2File, do nothing. Don't use the end_lock: exit path, as
  ** sqlite3_mutex_enter() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    OSTRACE(( "LOCK %d %d ok (already held)\n", pFile->h, locktype ));
    return SQLITE_OK;
  }

  /* Make sure the locking sequence is correct
  */
  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  assert( locktype!=PENDING_LOCK );
  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );

  /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
  ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
  ** the PENDING_LOCK byte is temporary.
  */
  newLocktype = pFile->locktype;
  if( pFile->locktype==NO_LOCK
      || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
  ){
    LockArea.lOffset = PENDING_BYTE;
    LockArea.lRange = 1L;
    UnlockArea.lOffset = 0L;
    UnlockArea.lRange = 0L;

    /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
    if( res == NO_ERROR ){
      gotPendingLock = 1;
      OSTRACE(( "LOCK %d pending lock boolean set.  res=%d\n", pFile->h, res ));
    }
  }

  /* Acquire a shared lock
  */
  if( locktype==SHARED_LOCK && res == NO_ERROR ){
    assert( pFile->locktype==NO_LOCK );
    res = getReadLock(pFile);
    if( res == NO_ERROR ){
      newLocktype = SHARED_LOCK;
    }
    OSTRACE(( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ));
  }

  /* Acquire a RESERVED lock
  */
  if( locktype==RESERVED_LOCK && res == NO_ERROR ){
    assert( pFile->locktype==SHARED_LOCK );
    LockArea.lOffset = RESERVED_BYTE;
    LockArea.lRange = 1L;
    UnlockArea.lOffset = 0L;
    UnlockArea.lRange = 0L;
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    if( res == NO_ERROR ){
      newLocktype = RESERVED_LOCK;
    }
    OSTRACE(( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ));
  }

  /* Acquire a PENDING lock
  */
  if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
    newLocktype = PENDING_LOCK;
    gotPendingLock = 0;
    OSTRACE(( "LOCK %d acquire pending lock. pending lock boolean unset.\n",
               pFile->h ));
  }

  /* Acquire an EXCLUSIVE lock
  */
  if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
    assert( pFile->locktype>=SHARED_LOCK );
    res = unlockReadLock(pFile);
    OSTRACE(( "unreadlock = %d\n", res ));
    LockArea.lOffset = SHARED_FIRST;
    LockArea.lRange = SHARED_SIZE;
    UnlockArea.lOffset = 0L;
    UnlockArea.lRange = 0L;
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    if( res == NO_ERROR ){
      newLocktype = EXCLUSIVE_LOCK;
    }else{
      OSTRACE(( "OS/2 error-code = %d\n", res ));
      getReadLock(pFile);
    }
    OSTRACE(( "LOCK %d acquire exclusive lock.  res=%d\n", pFile->h, res ));
  }

  /* If we are holding a PENDING lock that ought to be released, then
  ** release it now.
  */
  if( gotPendingLock && locktype==SHARED_LOCK ){
    int r;
    LockArea.lOffset = 0L;
    LockArea.lRange = 0L;
    UnlockArea.lOffset = PENDING_BYTE;
    UnlockArea.lRange = 1L;
    r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    OSTRACE(( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ));
  }

  /* Update the state of the lock has held in the file descriptor then
  ** return the appropriate result code.
  */
  if( res == NO_ERROR ){
    rc = SQLITE_OK;
  }else{
    OSTRACE(( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
              locktype, newLocktype ));
    rc = SQLITE_BUSY;
  }
  pFile->locktype = newLocktype;
  OSTRACE(( "LOCK %d now %d\n", pFile->h, pFile->locktype ));
  return rc;
}

/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, return
** non-zero, otherwise zero.
*/
static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
  int r = 0;
  os2File *pFile = (os2File*)id;
  assert( pFile!=0 );
  if( pFile->locktype>=RESERVED_LOCK ){
    r = 1;
    OSTRACE(( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ));
  }else{
    FILELOCK  LockArea,
              UnlockArea;
    APIRET rc = NO_ERROR;
    memset(&LockArea, 0, sizeof(LockArea));
    memset(&UnlockArea, 0, sizeof(UnlockArea));
    LockArea.lOffset = RESERVED_BYTE;
    LockArea.lRange = 1L;
    UnlockArea.lOffset = 0L;
    UnlockArea.lRange = 0L;
    rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    OSTRACE(( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ));
    if( rc == NO_ERROR ){
      APIRET rcu = NO_ERROR; /* return code for unlocking */
      LockArea.lOffset = 0L;
      LockArea.lRange = 0L;
      UnlockArea.lOffset = RESERVED_BYTE;
      UnlockArea.lRange = 1L;
      rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
      OSTRACE(( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ));
    }
    r = !(rc == NO_ERROR);
    OSTRACE(( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ));
  }
  *pOut = r;
  return SQLITE_OK;
}

/*
** Lower the locking level on file descriptor id to locktype.  locktype
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
**
** It is not possible for this routine to fail if the second argument
** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
** might return SQLITE_IOERR;
*/
static int os2Unlock( sqlite3_file *id, int locktype ){
  int type;
  os2File *pFile = (os2File*)id;
  APIRET rc = SQLITE_OK;
  APIRET res = NO_ERROR;
  FILELOCK  LockArea,
            UnlockArea;
  memset(&LockArea, 0, sizeof(LockArea));
  memset(&UnlockArea, 0, sizeof(UnlockArea));
  assert( pFile!=0 );
  assert( locktype<=SHARED_LOCK );
  OSTRACE(( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ));
  type = pFile->locktype;
  if( type>=EXCLUSIVE_LOCK ){
    LockArea.lOffset = 0L;
    LockArea.lRange = 0L;
    UnlockArea.lOffset = SHARED_FIRST;
    UnlockArea.lRange = SHARED_SIZE;
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    OSTRACE(( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ));
    if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
      /* This should never happen.  We should always be able to
      ** reacquire the read lock */
      OSTRACE(( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ));
      rc = SQLITE_IOERR_UNLOCK;
    }
  }
  if( type>=RESERVED_LOCK ){
    LockArea.lOffset = 0L;
    LockArea.lRange = 0L;
    UnlockArea.lOffset = RESERVED_BYTE;
    UnlockArea.lRange = 1L;
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    OSTRACE(( "UNLOCK %d reserved res=%d\n", pFile->h, res ));
  }
  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
    res = unlockReadLock(pFile);
    OSTRACE(( "UNLOCK %d is %d want %d res=%d\n",
              pFile->h, type, locktype, res ));
  }
  if( type>=PENDING_LOCK ){
    LockArea.lOffset = 0L;
    LockArea.lRange = 0L;
    UnlockArea.lOffset = PENDING_BYTE;
    UnlockArea.lRange = 1L;
    res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
    OSTRACE(( "UNLOCK %d pending res=%d\n", pFile->h, res ));
  }
  pFile->locktype = locktype;
  OSTRACE(( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ));
  return rc;
}

/*
** Control and query of the open file handle.
*/
static int os2FileControl(sqlite3_file *id, int op, void *pArg){
  switch( op ){
    case SQLITE_FCNTL_LOCKSTATE: {
      *(int*)pArg = ((os2File*)id)->locktype;
      OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n",
                ((os2File*)id)->h, ((os2File*)id)->locktype ));
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      ((os2File*)id)->szChunk = *(int*)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
      SimulateIOErrorBenign(1);
      os2Truncate(id, sz);
      SimulateIOErrorBenign(0);
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SYNC_OMITTED: {
      return SQLITE_OK;
    }
  }
  return SQLITE_NOTFOUND;
}

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and its journal file) that the sector size will be the
** same for both.
*/
static int os2SectorSize(sqlite3_file *id){
  UNUSED_PARAMETER(id);
  return SQLITE_DEFAULT_SECTOR_SIZE;
}

/*
** Return a vector of device characteristics.
*/
static int os2DeviceCharacteristics(sqlite3_file *id){
  UNUSED_PARAMETER(id);
  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
}


/*
** Character set conversion objects used by conversion routines.
*/
static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */
static UconvObject uclCp = NULL;  /* convert between local codepage and UCS-2 */

/*
** Helper function to initialize the conversion objects from and to UTF-8.
*/
static void initUconvObjects( void ){
  if( UniCreateUconvObject( UTF_8, &ucUtf8 ) != ULS_SUCCESS )
    ucUtf8 = NULL;
  if ( UniCreateUconvObject( (UniChar *)L"@path=yes", &uclCp ) != ULS_SUCCESS )
    uclCp = NULL;
}

/*
** Helper function to free the conversion objects from and to UTF-8.
*/
static void freeUconvObjects( void ){
  if ( ucUtf8 )
    UniFreeUconvObject( ucUtf8 );
  if ( uclCp )
    UniFreeUconvObject( uclCp );
  ucUtf8 = NULL;
  uclCp = NULL;
}

/*
** Helper function to convert UTF-8 filenames to local OS/2 codepage.
** The two-step process: first convert the incoming UTF-8 string
** into UCS-2 and then from UCS-2 to the current codepage.
** The returned char pointer has to be freed.
*/
static char *convertUtf8PathToCp( const char *in ){
  UniChar tempPath[CCHMAXPATH];
  char *out = (char *)calloc( CCHMAXPATH, 1 );

  if( !out )
    return NULL;

  if( !ucUtf8 || !uclCp )
    initUconvObjects();

  /* determine string for the conversion of UTF-8 which is CP1208 */
  if( UniStrToUcs( ucUtf8, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
    return out; /* if conversion fails, return the empty string */

  /* conversion for current codepage which can be used for paths */
  UniStrFromUcs( uclCp, out, tempPath, CCHMAXPATH );

  return out;
}

/*
** Helper function to convert filenames from local codepage to UTF-8.
** The two-step process: first convert the incoming codepage-specific
** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
** The returned char pointer has to be freed.
**
** This function is non-static to be able to use this in shell.c and
** similar applications that take command line arguments.
*/
char *convertCpPathToUtf8( const char *in ){
  UniChar tempPath[CCHMAXPATH];
  char *out = (char *)calloc( CCHMAXPATH, 1 );

  if( !out )
    return NULL;

  if( !ucUtf8 || !uclCp )
    initUconvObjects();

  /* conversion for current codepage which can be used for paths */
  if( UniStrToUcs( uclCp, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
    return out; /* if conversion fails, return the empty string */

  /* determine string for the conversion of UTF-8 which is CP1208 */
  UniStrFromUcs( ucUtf8, out, tempPath, CCHMAXPATH );

  return out;
}


#ifndef SQLITE_OMIT_WAL

/*
** Use main database file for interprocess locking. If un-defined
** a separate file is created for this purpose. The file will be
** used only to set file locks. There will be no data written to it.
*/
#define SQLITE_OS2_NO_WAL_LOCK_FILE     

#if 0
static void _ERR_TRACE( const char *fmt, ... ) {
  va_list  ap;
  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  fflush(stderr);
}
#define ERR_TRACE(rc, msg)        \
        if( (rc) != SQLITE_OK ) _ERR_TRACE msg;
#else
#define ERR_TRACE(rc, msg)
#endif

/*
** Helper functions to obtain and relinquish the global mutex. The
** global mutex is used to protect os2ShmNodeList.
**
** Function os2ShmMutexHeld() is used to assert() that the global mutex 
** is held when required. This function is only used as part of assert() 
** statements. e.g.
**
**   os2ShmEnterMutex()
**     assert( os2ShmMutexHeld() );
**   os2ShmLeaveMutex()
*/
static void os2ShmEnterMutex(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void os2ShmLeaveMutex(void){
  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
#ifdef SQLITE_DEBUG
static int os2ShmMutexHeld(void) {
  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
int GetCurrentProcessId(void) {
  PPIB pib;
  DosGetInfoBlocks(NULL, &pib);
  return (int)pib->pib_ulpid;
}
#endif

/*
** Object used to represent a the shared memory area for a single log file.
** When multiple threads all reference the same log-summary, each thread has
** its own os2File object, but they all point to a single instance of this 
** object.  In other words, each log-summary is opened only once per process.
**
** os2ShmMutexHeld() must be true when creating or destroying
** this object or while reading or writing the following fields:
**
**      nRef
**      pNext 
**
** The following fields are read-only after the object is created:
** 
**      szRegion
**      hLockFile
**      shmBaseName
**
** Either os2ShmNode.mutex must be held or os2ShmNode.nRef==0 and
** os2ShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
*/
struct os2ShmNode {
  sqlite3_mutex *mutex;      /* Mutex to access this object */
  os2ShmNode *pNext;         /* Next in list of all os2ShmNode objects */

  int szRegion;              /* Size of shared-memory regions */

  int nRegion;               /* Size of array apRegion */
  void **apRegion;           /* Array of pointers to shared-memory regions */

  int nRef;                  /* Number of os2ShmLink objects pointing to this */
  os2ShmLink *pFirst;        /* First os2ShmLink object pointing to this */

  HFILE hLockFile;           /* File used for inter-process memory locking */
  char shmBaseName[1];       /* Name of the memory object !!! must last !!! */
};


/*
** Structure used internally by this VFS to record the state of an
** open shared memory connection.
**
** The following fields are initialized when this object is created and
** are read-only thereafter:
**
**    os2Shm.pShmNode
**    os2Shm.id
**
** All other fields are read/write.  The os2Shm.pShmNode->mutex must be held
** while accessing any read/write fields.
*/
struct os2ShmLink {
  os2ShmNode *pShmNode;      /* The underlying os2ShmNode object */
  os2ShmLink *pNext;         /* Next os2Shm with the same os2ShmNode */
  u32 sharedMask;            /* Mask of shared locks held */
  u32 exclMask;              /* Mask of exclusive locks held */
#ifdef SQLITE_DEBUG
  u8 id;                     /* Id of this connection with its os2ShmNode */
#endif
};


/*
** A global list of all os2ShmNode objects.
**
** The os2ShmMutexHeld() must be true while reading or writing this list.
*/
static os2ShmNode *os2ShmNodeList = NULL;

/*
** Constants used for locking
*/
#ifdef  SQLITE_OS2_NO_WAL_LOCK_FILE
#define OS2_SHM_BASE   (PENDING_BYTE + 0x10000)         /* first lock byte */
#else
#define OS2_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
#endif

#define OS2_SHM_DMS    (OS2_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */

/*
** Apply advisory locks for all n bytes beginning at ofst.
*/
#define _SHM_UNLCK  1   /* no lock */
#define _SHM_RDLCK  2   /* shared lock, no wait */
#define _SHM_WRLCK  3   /* exlusive lock, no wait */
#define _SHM_WRLCK_WAIT 4 /* exclusive lock, wait */
static int os2ShmSystemLock(
  os2ShmNode *pNode,    /* Apply locks to this open shared-memory segment */
  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, _SHM_WRLCK or _SHM_WRLCK_WAIT */
  int ofst,             /* Offset to first byte to be locked/unlocked */
  int nByte             /* Number of bytes to lock or unlock */
){
  APIRET rc;
  FILELOCK area;
  ULONG mode, timeout;

  /* Access to the os2ShmNode object is serialized by the caller */
  assert( sqlite3_mutex_held(pNode->mutex) || pNode->nRef==0 );

  mode = 1;     /* shared lock */
  timeout = 0;  /* no wait */
  area.lOffset = ofst;
  area.lRange = nByte;

  switch( lockType ) {
    case _SHM_WRLCK_WAIT:
      timeout = (ULONG)-1;      /* wait forever */
    case _SHM_WRLCK:
      mode = 0;                 /* exclusive lock */
    case _SHM_RDLCK:
      rc = DosSetFileLocks(pNode->hLockFile, 
                           NULL, &area, timeout, mode);
      break;
    /* case _SHM_UNLCK: */
    default:
      rc = DosSetFileLocks(pNode->hLockFile, 
                           &area, NULL, 0, 0);
      break;
  }
                          
  OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", 
           pNode->hLockFile,
           rc==SQLITE_OK ? "ok" : "failed",
           lockType==_SHM_UNLCK ? "Unlock" : "Lock",
           rc));

  ERR_TRACE(rc, ("os2ShmSystemLock: %d %s\n", rc, pNode->shmBaseName))

  return ( rc == 0 ) ?  SQLITE_OK : SQLITE_BUSY;
}

/*
** Find an os2ShmNode in global list or allocate a new one, if not found.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static int os2OpenSharedMemory( os2File *fd, int szRegion ) {
  os2ShmLink *pLink;
  os2ShmNode *pNode;
  int cbShmName, rc = SQLITE_OK;
  char shmName[CCHMAXPATH + 30];
#ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
  ULONG action;
#endif
  
  /* We need some additional space at the end to append the region number */
  cbShmName = sprintf(shmName, "\\SHAREMEM\\%s", fd->zFullPathCp );
  if( cbShmName >= CCHMAXPATH-8 )
    return SQLITE_IOERR_SHMOPEN; 

  /* Replace colon in file name to form a valid shared memory name */
  shmName[10+1] = '!';

  /* Allocate link object (we free it later in case of failure) */
  pLink = sqlite3_malloc( sizeof(*pLink) );
  if( !pLink )
    return SQLITE_NOMEM;

  /* Access node list */
  os2ShmEnterMutex();

  /* Find node by it's shared memory base name */
  for( pNode = os2ShmNodeList; 
       pNode && stricmp(shmName, pNode->shmBaseName) != 0; 
       pNode = pNode->pNext )   ;

  /* Not found: allocate a new node */
  if( !pNode ) {
    pNode = sqlite3_malloc( sizeof(*pNode) + cbShmName );
    if( pNode ) {
      memset(pNode, 0, sizeof(*pNode) );
      pNode->szRegion = szRegion;
      pNode->hLockFile = (HFILE)-1;      
      strcpy(pNode->shmBaseName, shmName);

#ifdef SQLITE_OS2_NO_WAL_LOCK_FILE
      if( DosDupHandle(fd->h, &pNode->hLockFile) != 0 ) {
#else
      sprintf(shmName, "%s-lck", fd->zFullPathCp);
      if( DosOpen((PSZ)shmName, &pNode->hLockFile, &action, 0, FILE_NORMAL, 
                  OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,
                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | 
                  OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR,
                  NULL) != 0 ) {
#endif
        sqlite3_free(pNode);  
        rc = SQLITE_IOERR;
      } else {
        pNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
        if( !pNode->mutex ) {
          sqlite3_free(pNode);  
          rc = SQLITE_NOMEM;
        }
      }   
    } else {
      rc = SQLITE_NOMEM;
    }
    
    if( rc == SQLITE_OK ) {
      pNode->pNext = os2ShmNodeList;
      os2ShmNodeList = pNode;
    } else {
      pNode = NULL;
    }
  } else if( pNode->szRegion != szRegion ) {
    rc = SQLITE_IOERR_SHMSIZE;
    pNode = NULL;
  }

  if( pNode ) {
    sqlite3_mutex_enter(pNode->mutex);

    memset(pLink, 0, sizeof(*pLink));

    pLink->pShmNode = pNode;
    pLink->pNext = pNode->pFirst;
    pNode->pFirst = pLink;
    pNode->nRef++;

    fd->pShmLink = pLink;

    sqlite3_mutex_leave(pNode->mutex);
    
  } else {
    /* Error occured. Free our link object. */
    sqlite3_free(pLink);  
  }

  os2ShmLeaveMutex();

  ERR_TRACE(rc, ("os2OpenSharedMemory: %d  %s\n", rc, fd->zFullPathCp))  
  
  return rc;
}

/*
** Purge the os2ShmNodeList list of all entries with nRef==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static void os2PurgeShmNodes( int deleteFlag ) {
  os2ShmNode *pNode;
  os2ShmNode **ppNode;

  os2ShmEnterMutex();
  
  ppNode = &os2ShmNodeList;

  while( *ppNode ) {
    pNode = *ppNode;

    if( pNode->nRef == 0 ) {
      *ppNode = pNode->pNext;   
     
      if( pNode->apRegion ) {
        /* Prevent other processes from resizing the shared memory */
        os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);

        while( pNode->nRegion-- ) {
#ifdef SQLITE_DEBUG
          int rc = 
#endif          
          DosFreeMem(pNode->apRegion[pNode->nRegion]);

          OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
                  (int)GetCurrentProcessId(), pNode->nRegion,
                  rc == 0 ? "ok" : "failed"));
        }

        /* Allow other processes to resize the shared memory */
        os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);

        sqlite3_free(pNode->apRegion);
      }  

      DosClose(pNode->hLockFile);
      
#ifndef SQLITE_OS2_NO_WAL_LOCK_FILE
      if( deleteFlag ) {
         char fileName[CCHMAXPATH];
         /* Skip "\\SHAREMEM\\" */
         sprintf(fileName, "%s-lck", pNode->shmBaseName + 10);
         /* restore colon */
         fileName[1] = ':';
         
         DosForceDelete(fileName); 
      }
#endif

      sqlite3_mutex_free(pNode->mutex);

      sqlite3_free(pNode);
      
    } else {
      ppNode = &pNode->pNext;
    }
  } 

  os2ShmLeaveMutex();
}

/*
** This function is called to obtain a pointer to region iRegion of the
** shared-memory associated with the database file id. Shared-memory regions
** are numbered starting from zero. Each shared-memory region is szRegion
** bytes in size.
**
** If an error occurs, an error code is returned and *pp is set to NULL.
**
** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
** region has not been allocated (by any client, including one running in a
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
** bExtend is non-zero and the requested shared-memory region has not yet
** been allocated, it is allocated by this function.
**
** If the shared-memory region has already been allocated or is allocated by
** this call as described above, then it is mapped into this processes
** address space (if it is not already), *pp is set to point to the mapped
** memory and SQLITE_OK returned.
*/
static int os2ShmMap(
  sqlite3_file *id,               /* Handle open on database file */
  int iRegion,                    /* Region to retrieve */
  int szRegion,                   /* Size of regions */
  int bExtend,                    /* True to extend block if necessary */
  void volatile **pp              /* OUT: Mapped memory */
){
  PVOID pvTemp;
  void **apRegion;
  os2ShmNode *pNode;
  int n, rc = SQLITE_OK;
  char shmName[CCHMAXPATH];
  os2File *pFile = (os2File*)id;
  
  *pp = NULL;

  if( !pFile->pShmLink )
    rc = os2OpenSharedMemory( pFile, szRegion );
  
  if( rc == SQLITE_OK ) {
    pNode = pFile->pShmLink->pShmNode ;
    
    sqlite3_mutex_enter(pNode->mutex);
    
    assert( szRegion==pNode->szRegion );

    /* Unmapped region ? */
    if( iRegion >= pNode->nRegion ) {
      /* Prevent other processes from resizing the shared memory */
      os2ShmSystemLock(pNode, _SHM_WRLCK_WAIT, OS2_SHM_DMS, 1);

      apRegion = sqlite3_realloc(
        pNode->apRegion, (iRegion + 1) * sizeof(apRegion[0]));

      if( apRegion ) {
        pNode->apRegion = apRegion;

        while( pNode->nRegion <= iRegion ) {
          sprintf(shmName, "%s-%u", 
                  pNode->shmBaseName, pNode->nRegion);

          if( DosGetNamedSharedMem(&pvTemp, (PSZ)shmName, 
                PAG_READ | PAG_WRITE) != NO_ERROR ) {
            if( !bExtend )
              break;

            if( DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
                  PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_ANY) != NO_ERROR && 
                DosAllocSharedMem(&pvTemp, (PSZ)shmName, szRegion,
                  PAG_READ | PAG_WRITE | PAG_COMMIT) != NO_ERROR ) { 
              rc = SQLITE_NOMEM;
              break;
            }
          }

          apRegion[pNode->nRegion++] = pvTemp;
        }

        /* zero out remaining entries */ 
        for( n = pNode->nRegion; n <= iRegion; n++ )
          pNode->apRegion[n] = NULL;

        /* Return this region (maybe zero) */
        *pp = pNode->apRegion[iRegion];
      } else {
        rc = SQLITE_NOMEM;
      }

      /* Allow other processes to resize the shared memory */
      os2ShmSystemLock(pNode, _SHM_UNLCK, OS2_SHM_DMS, 1);
      
    } else {
      /* Region has been mapped previously */
      *pp = pNode->apRegion[iRegion];
    }

    sqlite3_mutex_leave(pNode->mutex);
  } 

  ERR_TRACE(rc, ("os2ShmMap: %s iRgn = %d, szRgn = %d, bExt = %d : %d\n", 
                 pFile->zFullPathCp, iRegion, szRegion, bExtend, rc))
          
  return rc;
}

/*
** Close a connection to shared-memory.  Delete the underlying
** storage if deleteFlag is true.
**
** If there is no shared memory associated with the connection then this
** routine is a harmless no-op.
*/
static int os2ShmUnmap(
  sqlite3_file *id,               /* The underlying database file */
  int deleteFlag                  /* Delete shared-memory if true */
){
  os2File *pFile = (os2File*)id;
  os2ShmLink *pLink = pFile->pShmLink;
  
  if( pLink ) {
    int nRef = -1;
    os2ShmLink **ppLink;
    os2ShmNode *pNode = pLink->pShmNode;

    sqlite3_mutex_enter(pNode->mutex);
    
    for( ppLink = &pNode->pFirst;
         *ppLink && *ppLink != pLink;
         ppLink = &(*ppLink)->pNext )   ;
         
    assert(*ppLink);

    if( *ppLink ) {
      *ppLink = pLink->pNext;
      nRef = --pNode->nRef;
    } else {
      ERR_TRACE(1, ("os2ShmUnmap: link not found ! %s\n", 
                    pNode->shmBaseName))
    }
    
    pFile->pShmLink = NULL;
    sqlite3_free(pLink);

    sqlite3_mutex_leave(pNode->mutex);
    
    if( nRef == 0 )
      os2PurgeShmNodes( deleteFlag );
  }

  return SQLITE_OK;
}

/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
** different here than in posix.  In xShmLock(), one can go from unlocked
** to shared and back or from unlocked to exclusive and back.  But one may
** not go from shared to exclusive or from exclusive to shared.
*/
static int os2ShmLock(
  sqlite3_file *id,          /* Database file holding the shared memory */
  int ofst,                  /* First lock to acquire or release */
  int n,                     /* Number of locks to acquire or release */
  int flags                  /* What to do with the lock */
){
  u32 mask;                             /* Mask of locks to take or release */
  int rc = SQLITE_OK;                   /* Result code */
  os2File *pFile = (os2File*)id;
  os2ShmLink *p = pFile->pShmLink;      /* The shared memory being locked */
  os2ShmLink *pX;                       /* For looping over all siblings */
  os2ShmNode *pShmNode = p->pShmNode;   /* Our node */
  
  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
  assert( n>=1 );
  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );

  mask = (u32)((1U<<(ofst+n)) - (1U<<ofst));
  assert( n>1 || mask==(1<<ofst) );


  sqlite3_mutex_enter(pShmNode->mutex);

  if( flags & SQLITE_SHM_UNLOCK ){
    u32 allMask = 0; /* Mask of locks held by siblings */

    /* See if any siblings hold this same lock */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( pX==p ) continue;
      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
      allMask |= pX->sharedMask;
    }

    /* Unlock the system-level locks */
    if( (mask & allMask)==0 ){
      rc = os2ShmSystemLock(pShmNode, _SHM_UNLCK, ofst+OS2_SHM_BASE, n);
    }else{
      rc = SQLITE_OK;
    }

    /* Undo the local locks */
    if( rc==SQLITE_OK ){
      p->exclMask &= ~mask;
      p->sharedMask &= ~mask;
    } 
  }else if( flags & SQLITE_SHM_SHARED ){
    u32 allShared = 0;  /* Union of locks held by connections other than "p" */

    /* Find out which shared locks are already held by sibling connections.
    ** If any sibling already holds an exclusive lock, go ahead and return
    ** SQLITE_BUSY.
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 ){
        rc = SQLITE_BUSY;
        break;
      }
      allShared |= pX->sharedMask;
    }

    /* Get shared locks at the system level, if necessary */
    if( rc==SQLITE_OK ){
      if( (allShared & mask)==0 ){
        rc = os2ShmSystemLock(pShmNode, _SHM_RDLCK, ofst+OS2_SHM_BASE, n);
      }else{
        rc = SQLITE_OK;
      }
    }

    /* Get the local shared locks */
    if( rc==SQLITE_OK ){
      p->sharedMask |= mask;
    }
  }else{
    /* Make sure no sibling connections hold locks that will block this
    ** lock.  If any do, return SQLITE_BUSY right away.
    */
    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
        rc = SQLITE_BUSY;
        break;
      }
    }
  
    /* Get the exclusive locks at the system level.  Then if successful
    ** also mark the local connection as being locked.
    */
    if( rc==SQLITE_OK ){
      rc = os2ShmSystemLock(pShmNode, _SHM_WRLCK, ofst+OS2_SHM_BASE, n);
      if( rc==SQLITE_OK ){
        assert( (p->sharedMask & mask)==0 );
        p->exclMask |= mask;
      }
    }
  }

  sqlite3_mutex_leave(pShmNode->mutex);
  
  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
           p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
           rc ? "failed" : "ok"));

  ERR_TRACE(rc, ("os2ShmLock: ofst = %d, n = %d, flags = 0x%x -> %d \n", 
                 ofst, n, flags, rc))
                  
  return rc; 
}

/*
** Implement a memory barrier or memory fence on shared memory.
**
** All loads and stores begun before the barrier must complete before
** any load or store begun after the barrier.
*/
static void os2ShmBarrier(
  sqlite3_file *id                /* Database file holding the shared memory */
){
  UNUSED_PARAMETER(id);
  os2ShmEnterMutex();
  os2ShmLeaveMutex();
}

#else
# define os2ShmMap     0
# define os2ShmLock    0
# define os2ShmBarrier 0
# define os2ShmUnmap   0
#endif /* #ifndef SQLITE_OMIT_WAL */


/*
** This vector defines all the methods that can operate on an
** sqlite3_file for os2.
*/
static const sqlite3_io_methods os2IoMethod = {
  2,                              /* iVersion */
  os2Close,                       /* xClose */
  os2Read,                        /* xRead */
  os2Write,                       /* xWrite */
  os2Truncate,                    /* xTruncate */
  os2Sync,                        /* xSync */
  os2FileSize,                    /* xFileSize */
  os2Lock,                        /* xLock */
  os2Unlock,                      /* xUnlock */
  os2CheckReservedLock,           /* xCheckReservedLock */
  os2FileControl,                 /* xFileControl */
  os2SectorSize,                  /* xSectorSize */
  os2DeviceCharacteristics,       /* xDeviceCharacteristics */
  os2ShmMap,                      /* xShmMap */
  os2ShmLock,                     /* xShmLock */
  os2ShmBarrier,                  /* xShmBarrier */
  os2ShmUnmap                     /* xShmUnmap */
};


/***************************************************************************
** Here ends the I/O methods that form the sqlite3_io_methods object.
**
** The next block of code implements the VFS methods.
****************************************************************************/

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at pVfs->mxPathname characters.
*/
static int getTempname(int nBuf, char *zBuf ){
  static const char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  int i, j;
  PSZ zTempPathCp;      
  char zTempPath[CCHMAXPATH];
  ULONG ulDriveNum, ulDriveMap;
  
  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  SimulateIOError( return SQLITE_IOERR );

  if( sqlite3_temp_directory ) {
    sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", sqlite3_temp_directory);
  } else if( DosScanEnv( (PSZ)"TEMP",   &zTempPathCp ) == NO_ERROR ||
             DosScanEnv( (PSZ)"TMP",    &zTempPathCp ) == NO_ERROR ||
             DosScanEnv( (PSZ)"TMPDIR", &zTempPathCp ) == NO_ERROR ) {
    char *zTempPathUTF = convertCpPathToUtf8( (char *)zTempPathCp );
    sqlite3_snprintf(CCHMAXPATH-30, zTempPath, "%s", zTempPathUTF);
    free( zTempPathUTF );
  } else if( DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ) == NO_ERROR ) {
    zTempPath[0] = (char)('A' + ulDriveNum - 1);
    zTempPath[1] = ':'; 
    zTempPath[2] = '\0'; 
  } else {
    zTempPath[0] = '\0'; 
  }
  
  /* Strip off a trailing slashes or backslashes, otherwise we would get *
   * multiple (back)slashes which causes DosOpen() to fail.              *
   * Trailing spaces are not allowed, either.                            */
  j = sqlite3Strlen30(zTempPath);
  while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' || 
                    zTempPath[j-1] == ' ' ) ){
    j--;
  }
  zTempPath[j] = '\0';
  
  /* We use 20 bytes to randomize the name */
  sqlite3_snprintf(nBuf-22, zBuf,
                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
  j = sqlite3Strlen30(zBuf);
  sqlite3_randomness( 20, &zBuf[j] );
  for( i = 0; i < 20; i++, j++ ){
    zBuf[j] = zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  }
  zBuf[j] = 0;

  OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
  return SQLITE_OK;
}


/*
** Turn a relative pathname into a full pathname.  Write the full
** pathname into zFull[].  zFull[] will be at least pVfs->mxPathname
** bytes in size.
*/
static int os2FullPathname(
  sqlite3_vfs *pVfs,          /* Pointer to vfs object */
  const char *zRelative,      /* Possibly relative input path */
  int nFull,                  /* Size of output buffer in bytes */
  char *zFull                 /* Output buffer */
){
  char *zRelativeCp = convertUtf8PathToCp( zRelative );
  char zFullCp[CCHMAXPATH] = "\0";
  char *zFullUTF;
  APIRET rc = DosQueryPathInfo( (PSZ)zRelativeCp, FIL_QUERYFULLNAME, 
                                zFullCp, CCHMAXPATH );
  free( zRelativeCp );
  zFullUTF = convertCpPathToUtf8( zFullCp );
  sqlite3_snprintf( nFull, zFull, zFullUTF );
  free( zFullUTF );
  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}


/*
** Open a file.
*/
static int os2Open(
  sqlite3_vfs *pVfs,            /* Not used */
  const char *zName,            /* Name of the file (UTF-8) */
  sqlite3_file *id,             /* Write the SQLite file handle here */
  int flags,                    /* Open mode flags */
  int *pOutFlags                /* Status return flags */
){
  HFILE h;
  ULONG ulOpenFlags = 0;
  ULONG ulOpenMode = 0;
  ULONG ulAction = 0;
  ULONG rc;
  os2File *pFile = (os2File*)id;
  const char *zUtf8Name = zName;
  char *zNameCp;
  char  zTmpname[CCHMAXPATH];

  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
  int isCreate     = (flags & SQLITE_OPEN_CREATE);
  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
#ifndef NDEBUG
  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
  int eType        = (flags & 0xFFFFFF00);
  int isOpenJournal = (isCreate && (
        eType==SQLITE_OPEN_MASTER_JOURNAL 
     || eType==SQLITE_OPEN_MAIN_JOURNAL 
     || eType==SQLITE_OPEN_WAL
  ));
#endif

  UNUSED_PARAMETER(pVfs);
  assert( id!=0 );

  /* Check the following statements are true: 
  **
  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
  **   (b) if CREATE is set, then READWRITE must also be set, and
  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
  */
  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
  assert(isCreate==0 || isReadWrite);
  assert(isExclusive==0 || isCreate);
  assert(isDelete==0 || isCreate);

  /* The main DB, main journal, WAL file and master journal are never 
  ** automatically deleted. Nor are they ever temporary files.  */
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );

  /* Assert that the upper layer has set one of the "file-type" flags. */
  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
  );

  memset( pFile, 0, sizeof(*pFile) );
  pFile->h = (HFILE)-1;

  /* If the second argument to this function is NULL, generate a 
  ** temporary file name to use 
  */
  if( !zUtf8Name ){
    assert(isDelete && !isOpenJournal);
    rc = getTempname(CCHMAXPATH, zTmpname);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    zUtf8Name = zTmpname;
  }

  if( isReadWrite ){
    ulOpenMode |= OPEN_ACCESS_READWRITE;
  }else{
    ulOpenMode |= OPEN_ACCESS_READONLY;
  }

  /* Open in random access mode for possibly better speed.  Allow full
  ** sharing because file locks will provide exclusive access when needed.
  ** The handle should not be inherited by child processes and we don't 
  ** want popups from the critical error handler.
  */
  ulOpenMode |= OPEN_FLAGS_RANDOM | OPEN_SHARE_DENYNONE | 
                OPEN_FLAGS_NOINHERIT | OPEN_FLAGS_FAIL_ON_ERROR;

  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 
  ** created. SQLite doesn't use it to indicate "exclusive access" 
  ** as it is usually understood.
  */
  if( isExclusive ){
    /* Creates a new file, only if it does not already exist. */
    /* If the file exists, it fails. */
    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
  }else if( isCreate ){
    /* Open existing file, or create if it doesn't exist */
    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
  }else{
    /* Opens a file, only if it exists. */
    ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
  }

  zNameCp = convertUtf8PathToCp( zUtf8Name );
  rc = DosOpen( (PSZ)zNameCp,
                &h,
                &ulAction,
                0L,
                FILE_NORMAL,
                ulOpenFlags,
                ulOpenMode,
                (PEAOP2)NULL );
  free( zNameCp );

  if( rc != NO_ERROR ){
    OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
              rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));

    if( isReadWrite ){
      return os2Open( pVfs, zName, id,
                      ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
                      pOutFlags );
    }else{
      return SQLITE_CANTOPEN;
    }
  }

  if( pOutFlags ){
    *pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
  }

  os2FullPathname( pVfs, zUtf8Name, sizeof( zTmpname ), zTmpname );
  pFile->zFullPathCp = convertUtf8PathToCp( zTmpname );
  pFile->pMethod = &os2IoMethod;
  pFile->flags = flags;
  pFile->h = h;

  OpenCounter(+1);
  OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
  return SQLITE_OK;
}

/*
** Delete the named file.
*/
static int os2Delete(
  sqlite3_vfs *pVfs,                     /* Not used on os2 */
  const char *zFilename,                 /* Name of file to delete */
  int syncDir                            /* Not used on os2 */
){
  APIRET rc;
  char *zFilenameCp;
  SimulateIOError( return SQLITE_IOERR_DELETE );
  zFilenameCp = convertUtf8PathToCp( zFilename );
  rc = DosDelete( (PSZ)zFilenameCp );
  free( zFilenameCp );
  OSTRACE(( "DELETE \"%s\"\n", zFilename ));
  return (rc == NO_ERROR ||
          rc == ERROR_FILE_NOT_FOUND ||
          rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
}

/*
** Check the existance and status of a file.
*/
static int os2Access(
  sqlite3_vfs *pVfs,        /* Not used on os2 */
  const char *zFilename,    /* Name of file to check */
  int flags,                /* Type of test to make on this file */
  int *pOut                 /* Write results here */
){
  APIRET rc;
  FILESTATUS3 fsts3ConfigInfo;
  char *zFilenameCp;

  UNUSED_PARAMETER(pVfs);
  SimulateIOError( return SQLITE_IOERR_ACCESS; );
  
  zFilenameCp = convertUtf8PathToCp( zFilename );
  rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
                         &fsts3ConfigInfo, sizeof(FILESTATUS3) );
  free( zFilenameCp );
  OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
            fsts3ConfigInfo.attrFile, flags, rc ));

  switch( flags ){
    case SQLITE_ACCESS_EXISTS:
      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
      ** as if it does not exist.
      */
      if( fsts3ConfigInfo.cbFile == 0 ) 
        rc = ERROR_FILE_NOT_FOUND;
      break;
    case SQLITE_ACCESS_READ:
      break;
    case SQLITE_ACCESS_READWRITE:
      if( fsts3ConfigInfo.attrFile & FILE_READONLY )
        rc = ERROR_ACCESS_DENIED;
      break;
    default:
      rc = ERROR_FILE_NOT_FOUND;
      assert( !"Invalid flags argument" );
  }

  *pOut = (rc == NO_ERROR);
  OSTRACE(( "ACCESS %s flags %d: rc=%d\n", zFilename, flags, *pOut ));

  return SQLITE_OK;
}


#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
/*
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
  HMODULE hmod;
  APIRET rc;
  char *zFilenameCp = convertUtf8PathToCp(zFilename);
  rc = DosLoadModule(NULL, 0, (PSZ)zFilenameCp, &hmod);
  free(zFilenameCp);
  return rc != NO_ERROR ? 0 : (void*)hmod;
}
/*
** A no-op since the error code is returned on the DosLoadModule call.
** os2Dlopen returns zero if DosLoadModule is not successful.
*/
static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
/* no-op */
}
static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
  PFN pfn;
  APIRET rc;
  rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)zSymbol, &pfn);
  if( rc != NO_ERROR ){
    /* if the symbol itself was not found, search again for the same
     * symbol with an extra underscore, that might be needed depending
     * on the calling convention */
    char _zSymbol[256] = "_";
    strncat(_zSymbol, zSymbol, 254);
    rc = DosQueryProcAddr((HMODULE)pHandle, 0L, (PSZ)_zSymbol, &pfn);
  }
  return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
}
static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
  DosFreeModule((HMODULE)pHandle);
}
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
  #define os2DlOpen 0
  #define os2DlError 0
  #define os2DlSym 0
  #define os2DlClose 0
#endif


/*
** Write up to nBuf bytes of randomness into zBuf.
*/
static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){
  int n = 0;
#if defined(SQLITE_TEST)
  n = nBuf;
  memset(zBuf, 0, nBuf);
#else
  int i;                           
  PPIB ppib;
  PTIB ptib;
  DATETIME dt; 
  static unsigned c = 0;
  /* Ordered by variation probability */
  static ULONG svIdx[6] = { QSV_MS_COUNT, QSV_TIME_LOW,
                            QSV_MAXPRMEM, QSV_MAXSHMEM,
                            QSV_TOTAVAILMEM, QSV_TOTRESMEM };

  /* 8 bytes; timezone and weekday don't increase the randomness much */
  if( (int)sizeof(dt)-3 <= nBuf - n ){
    c += 0x0100;
    DosGetDateTime(&dt);
    dt.year = (USHORT)((dt.year - 1900) | c);
    memcpy(&zBuf[n], &dt, sizeof(dt)-3);
    n += sizeof(dt)-3;
  }

  /* 4 bytes; PIDs and TIDs are 16 bit internally, so combine them */
  if( (int)sizeof(ULONG) <= nBuf - n ){
    DosGetInfoBlocks(&ptib, &ppib);
    *(PULONG)&zBuf[n] = MAKELONG(ppib->pib_ulpid,
                                 ptib->tib_ptib2->tib2_ultid);
    n += sizeof(ULONG);
  }

  /* Up to 6 * 4 bytes; variables depend on the system state */
  for( i = 0; i < 6 && (int)sizeof(ULONG) <= nBuf - n; i++ ){
    DosQuerySysInfo(svIdx[i], svIdx[i], 
                    (PULONG)&zBuf[n], sizeof(ULONG));
    n += sizeof(ULONG);
  } 
#endif

  return n;
}

/*
** Sleep for a little while.  Return the amount of time slept.
** The argument is the number of microseconds we want to sleep.
** The return value is the number of microseconds of sleep actually
** requested from the underlying operating system, a number which
** might be greater than or equal to the argument, but not less
** than the argument.
*/
static int os2Sleep( sqlite3_vfs *pVfs, int microsec ){
  DosSleep( (microsec/1000) );
  return microsec;
}

/*
** The following variable, if set to a non-zero value, becomes the result
** returned from sqlite3OsCurrentTime().  This is used for testing.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_current_time = 0;
#endif

/*
** Find the current time (in Universal Coordinated Time).  Write into *piNow
** the current time and date as a Julian Day number times 86_400_000.  In
** other words, write into *piNow the number of milliseconds since the Julian
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
** proleptic Gregorian calendar.
**
** On success, return 0.  Return 1 if the time and date cannot be found.
*/
static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
#ifdef SQLITE_TEST
  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
#endif
  int year, month, datepart, timepart;
 
  DATETIME dt;
  DosGetDateTime( &dt );

  year = dt.year;
  month = dt.month;

  /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html
  ** http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c
  ** Calculate the Julian days
  */
  datepart = (int)dt.day - 32076 +
    1461*(year + 4800 + (month - 14)/12)/4 +
    367*(month - 2 - (month - 14)/12*12)/12 -
    3*((year + 4900 + (month - 14)/12)/100)/4;

  /* Time in milliseconds, hours to noon added */
  timepart = 12*3600*1000 + dt.hundredths*10 + dt.seconds*1000 +
    ((int)dt.minutes + dt.timezone)*60*1000 + dt.hours*3600*1000;

  *piNow = (sqlite3_int64)datepart*86400*1000 + timepart;
   
#ifdef SQLITE_TEST
  if( sqlite3_current_time ){
    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
  }
#endif

  UNUSED_PARAMETER(pVfs);
  return 0;
}

/*
** Find the current time (in Universal Coordinated Time).  Write the
** current time and date as a Julian Day number into *prNow and
** return 0.  Return 1 if the time and date cannot be found.
*/
static int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
  int rc;
  sqlite3_int64 i;
  rc = os2CurrentTimeInt64(pVfs, &i);
  if( !rc ){
    *prNow = i/86400000.0;
  }
  return rc;
}

/*
** The idea is that this function works like a combination of
** GetLastError() and FormatMessage() on windows (or errno and
** strerror_r() on unix). After an error is returned by an OS
** function, SQLite calls this function with zBuf pointing to
** a buffer of nBuf bytes. The OS layer should populate the
** buffer with a nul-terminated UTF-8 encoded error message
** describing the last IO error to have occurred within the calling
** thread.
**
** If the error message is too large for the supplied buffer,
** it should be truncated. The return value of xGetLastError
** is zero if the error message fits in the buffer, or non-zero
** otherwise (if the message was truncated). If non-zero is returned,
** then it is not necessary to include the nul-terminator character
** in the output buffer.
**
** Not supplying an error message will have no adverse effect
** on SQLite. It is fine to have an implementation that never
** returns an error message:
**
**   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
**     assert(zBuf[0]=='\0');
**     return 0;
**   }
**
** However if an error message is supplied, it will be incorporated
** by sqlite into the error message available to the user using
** sqlite3_errmsg(), possibly making IO errors easier to debug.
*/
static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  assert(zBuf[0]=='\0');
  return 0;
}

/*
** Initialize and deinitialize the operating system interface.
*/
SQLITE_API int sqlite3_os_init(void){
  static sqlite3_vfs os2Vfs = {
    3,                 /* iVersion */
    sizeof(os2File),   /* szOsFile */
    CCHMAXPATH,        /* mxPathname */
    0,                 /* pNext */
    "os2",             /* zName */
    0,                 /* pAppData */

    os2Open,           /* xOpen */
    os2Delete,         /* xDelete */
    os2Access,         /* xAccess */
    os2FullPathname,   /* xFullPathname */
    os2DlOpen,         /* xDlOpen */
    os2DlError,        /* xDlError */
    os2DlSym,          /* xDlSym */
    os2DlClose,        /* xDlClose */
    os2Randomness,     /* xRandomness */
    os2Sleep,          /* xSleep */
    os2CurrentTime,    /* xCurrentTime */
    os2GetLastError,   /* xGetLastError */
    os2CurrentTimeInt64, /* xCurrentTimeInt64 */
    0,                 /* xSetSystemCall */
    0,                 /* xGetSystemCall */
    0                  /* xNextSystemCall */
  };
  sqlite3_vfs_register(&os2Vfs, 1);
  initUconvObjects();
/*  sqlite3OSTrace = 1; */
  return SQLITE_OK;
}
SQLITE_API int sqlite3_os_end(void){
  freeUconvObjects();
  return SQLITE_OK;
}

#endif /* SQLITE_OS_OS2 */

/************** End of os_os2.c **********************************************/
/************** Begin file os_unix.c *****************************************/
/*
** 2004 May 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
................................................................................
#endif
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
  unsigned fsFlags;                   /* cached details from statfs() */
#endif
#if OS_VXWORKS
  struct vxworksFileId *pId;          /* Unique file ID */
#endif
#ifndef NDEBUG
  /* The next group of variables are used to track whether or not the
  ** transaction counter in bytes 24-27 of database files are updated
  ** whenever any part of the database changes.  An assertion fault will
  ** occur if a file is updated without also updating the transaction
  ** counter.  This test is made to avoid new problems similar to the
  ** one described by ticket #3584. 
  */
................................................................................
#else
# define UNIXFILE_DIRSYNC    0x00
#endif
#define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
#define UNIXFILE_DELETE      0x20     /* Delete on close */
#define UNIXFILE_URI         0x40     /* Filename might have query parameters */
#define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
#define UNIXFILE_CHOWN      0x100     /* File ownership was changed */

/*
** Include code that is common to all os_*.c files
*/
/************** Include os_common.h in the middle of os_unix.c ***************/
/************** Begin file os_common.h ***************************************/
/*
................................................................................
**
** The safest way to deal with the problem is to always use this wrapper
** which always has the same well-defined interface.
*/
static int posixOpen(const char *zFile, int flags, int mode){
  return open(zFile, flags, mode);
}










/* Forward reference */
static int openDirectory(const char*, int*);

/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
................................................................................

  { "mkdir",        (sqlite3_syscall_ptr)mkdir,           0 },
#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)

  { "rmdir",        (sqlite3_syscall_ptr)rmdir,           0 },
#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)

  { "fchown",       (sqlite3_syscall_ptr)fchown,          0 },
#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)

  { "umask",        (sqlite3_syscall_ptr)umask,           0 },
#define osUmask     ((mode_t(*)(mode_t))aSyscall[21].pCurrent)

}; /* End of the overrideable system calls */

................................................................................
      if( rc!=SQLITE_BUSY ){
        pFile->lastErrno = tErrno;
      }
    }
  }
  

#ifndef NDEBUG
  /* Set up the transaction-counter change checking flags when
  ** transitioning from a SHARED to a RESERVED lock.  The change
  ** from SHARED to RESERVED marks the beginning of a normal
  ** write operation (not a hot journal rollback).
  */
  if( rc==SQLITE_OK
   && pFile->eFileLock<=SHARED_LOCK
................................................................................
  }
  unixEnterMutex();
  pInode = pFile->pInode;
  assert( pInode->nShared!=0 );
  if( pFile->eFileLock>SHARED_LOCK ){
    assert( pInode->eFileLock==pFile->eFileLock );

#ifndef NDEBUG
    /* When reducing a lock such that other processes can start
    ** reading the database file again, make sure that the
    ** transaction counter was updated if any part of the database
    ** file changed.  If the transaction counter is not updated,
    ** other connections to the same file might not realize that
    ** the file has changed and hence might not know to flush their
    ** cache.  The use of a stale cache can lead to database corruption.
................................................................................
  assert( pInode->nShared!=0 );
  if( pFile->eFileLock>SHARED_LOCK ){
    assert( pInode->eFileLock==pFile->eFileLock );
    SimulateIOErrorBenign(1);
    SimulateIOError( h=(-1) )
    SimulateIOErrorBenign(0);
    
#ifndef NDEBUG
    /* When reducing a lock such that other processes can start
    ** reading the database file again, make sure that the
    ** transaction counter was updated if any part of the database
    ** file changed.  If the transaction counter is not updated,
    ** other connections to the same file might not realize that
    ** the file has changed and hence might not know to flush their
    ** cache.  The use of a stale cache can lead to database corruption.
................................................................................
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

#ifndef NDEBUG
  /* If we are doing a normal write to a database file (as opposed to
  ** doing a hot-journal rollback or a write to some file other than a
  ** normal database file) then record the fact that the database
  ** has changed.  If the transaction counter is modified, record that
  ** fact too.
  */
  if( pFile->inNormalWrite ){
................................................................................
  }

  rc = robust_ftruncate(pFile->h, (off_t)nByte);
  if( rc ){
    pFile->lastErrno = errno;
    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
  }else{
#ifndef NDEBUG
    /* If we are doing a normal write to a database file (as opposed to
    ** doing a hot-journal rollback or a write to some file other than a
    ** normal database file) and we truncate the file to zero length,
    ** that effectively updates the change counter.  This might happen
    ** when restoring a database using the backup API from a zero-length
    ** source.
    */
................................................................................
      unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_VFSNAME: {
      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
      return SQLITE_OK;
    }
#ifndef NDEBUG
    /* The pager calls this method to signal that it has done
    ** a rollback and that the database is therefore unchanged and
    ** it hence it is OK for the transaction change counter to be
    ** unchanged.
    */
    case SQLITE_FCNTL_DB_UNCHANGED: {
      ((unixFile*)id)->dbUpdate = 0;
................................................................................
      if( pShmNode->h<0 ){
        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
        goto shm_open_err;
      }

      /* If this process is running as root, make sure that the SHM file
      ** is owned by the same user that owns the original database.  Otherwise,
      ** the original owner will not be able to connect. If this process is
      ** not root, the following fchown() will fail, but we don't care.  The
      ** if(){..} and the UNIXFILE_CHOWN flag are purely to silence compiler
      ** warnings.
      */
      if( osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid)==0 ){
        pDbFd->ctrlFlags |= UNIXFILE_CHOWN;
      }
  
      /* Check to see if another process is holding the dead-man switch.
      ** If not, truncate the file to zero length. 
      */
      rc = SQLITE_OK;
      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
        if( robust_ftruncate(pShmNode->h, 0) ){
................................................................................
    if( fd<0 ){
      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
      goto open_finished;
    }

    /* If this process is running as root and if creating a new rollback
    ** journal or WAL file, set the ownership of the journal or WAL to be
    ** the same as the original database.  If we are not running as root,
    ** then the fchown() call will fail, but that's ok.  The "if(){}" and
    ** the setting of the UNIXFILE_CHOWN flag are purely to silence compiler
    ** warnings from gcc.
    */
    if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
      if( osFchown(fd, uid, gid)==0 ){ p->ctrlFlags |= UNIXFILE_CHOWN; }
    }
  }
  assert( fd>=0 );
  if( pOutFlags ){
    *pOutFlags = flags;
  }

................................................................................
#endif

#endif /* !defined(_OS_COMMON_H_) */

/************** End of os_common.h *******************************************/
/************** Continuing where we left off in os_win.c *********************/








/*
** Some Microsoft compilers lack this definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 
#endif









/* Forward references */
typedef struct winShm winShm;           /* A connection to shared-memory */
typedef struct winShmNode winShmNode;   /* A region of shared-memory */

/*
** WinCE lacks native support for file locking so we have to fake it
................................................................................

/*
** Allowed values for winFile.ctrlFlags
*/
#define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
#define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */








/*
 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
 * various Win32 API heap functions instead of our own.
 */
#ifdef SQLITE_WIN32_MALLOC



















/*
 * The initial size of the Win32-specific heap.  This value may be zero.
 */
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
#endif
................................................................................
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_os_type = 0;
#else
static int sqlite3_os_type = 0;
#endif

/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
** testing and sandboxing.  The following array holds the names and pointers
** to all overrideable system calls.
*/
#if !SQLITE_OS_WINCE
#  define SQLITE_WIN32_HAS_ANSI
#endif

#if SQLITE_OS_WINCE || SQLITE_OS_WINNT
#  define SQLITE_WIN32_HAS_WIDE
#endif

#ifndef SYSCALL
#  define SYSCALL sqlite3_syscall_ptr
#endif

#if SQLITE_OS_WINCE
/*
** These macros are necessary because Windows CE does not natively support the
** Win32 APIs LockFile, UnlockFile, and LockFileEx.

 */



#  define LockFile(a,b,c,d,e)       winceLockFile(&a, b, c, d, e)
#  define UnlockFile(a,b,c,d,e)     winceUnlockFile(&a, b, c, d, e)
#  define LockFileEx(a,b,c,d,e,f)   winceLockFileEx(&a, b, c, d, e, f)

/*


** These are the special syscall hacks for Windows CE.  The locking related
** defines here refer to the macros defined just above.
 */

#  define osAreFileApisANSI()       1
#  define osLockFile                LockFile
#  define osUnlockFile              UnlockFile
#  define osLockFileEx              LockFileEx
#endif

static struct win_syscall {
  const char *zName;            /* Name of the sytem call */
  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
  sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
#if !SQLITE_OS_WINCE
  { "AreFileApisANSI",         (SYSCALL)AreFileApisANSI,         0 },

#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
#else
  { "AreFileApisANSI",         (SYSCALL)0,                       0 },
#endif





#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
  { "CharLowerW",              (SYSCALL)CharLowerW,              0 },
#else
  { "CharLowerW",              (SYSCALL)0,                       0 },
#endif

................................................................................
#else
  { "CreateFileA",             (SYSCALL)0,                       0 },
#endif

#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "CreateFileW",             (SYSCALL)CreateFileW,             0 },
#else
  { "CreateFileW",             (SYSCALL)0,                       0 },
#endif

#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
        LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)

  { "CreateFileMapping",       (SYSCALL)CreateFileMapping,       0 },

#define osCreateFileMapping ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
        DWORD,DWORD,DWORD,LPCTSTR))aSyscall[6].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "CreateFileMappingW",      (SYSCALL)CreateFileMappingW,      0 },
#else
  { "CreateFileMappingW",      (SYSCALL)0,                       0 },
#endif

#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
        DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "CreateMutexW",            (SYSCALL)CreateMutexW,            0 },
#else
  { "CreateMutexW",            (SYSCALL)0,                       0 },
#endif

#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
        LPCWSTR))aSyscall[8].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "DeleteFileA",             (SYSCALL)DeleteFileA,             0 },
#else
  { "DeleteFileA",             (SYSCALL)0,                       0 },
#endif

#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "DeleteFileW",             (SYSCALL)DeleteFileW,             0 },
#else
  { "DeleteFileW",             (SYSCALL)0,                       0 },
#endif

#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)

#if SQLITE_OS_WINCE
  { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
#else
  { "FileTimeToLocalFileTime", (SYSCALL)0,                       0 },
#endif

#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
        LPFILETIME))aSyscall[11].pCurrent)

#if SQLITE_OS_WINCE
  { "FileTimeToSystemTime",    (SYSCALL)FileTimeToSystemTime,    0 },
#else
  { "FileTimeToSystemTime",    (SYSCALL)0,                       0 },
#endif

#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
        LPSYSTEMTIME))aSyscall[12].pCurrent)

  { "FlushFileBuffers",        (SYSCALL)FlushFileBuffers,        0 },

#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "FormatMessageA",          (SYSCALL)FormatMessageA,          0 },
#else
  { "FormatMessageA",          (SYSCALL)0,                       0 },
#endif

#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
        DWORD,va_list*))aSyscall[14].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "FormatMessageW",          (SYSCALL)FormatMessageW,          0 },
#else
  { "FormatMessageW",          (SYSCALL)0,                       0 },
#endif

#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
        DWORD,va_list*))aSyscall[15].pCurrent)

  { "FreeLibrary",             (SYSCALL)FreeLibrary,             0 },

#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)

  { "GetCurrentProcessId",     (SYSCALL)GetCurrentProcessId,     0 },

#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)

#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
  { "GetDiskFreeSpaceA",       (SYSCALL)GetDiskFreeSpaceA,       0 },
#else
  { "GetDiskFreeSpaceA",       (SYSCALL)0,                       0 },
#endif

#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
        LPDWORD))aSyscall[18].pCurrent)

#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
  { "GetDiskFreeSpaceW",       (SYSCALL)GetDiskFreeSpaceW,       0 },
#else
  { "GetDiskFreeSpaceW",       (SYSCALL)0,                       0 },
#endif

#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
        LPDWORD))aSyscall[19].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "GetFileAttributesA",      (SYSCALL)GetFileAttributesA,      0 },
#else
  { "GetFileAttributesA",      (SYSCALL)0,                       0 },
#endif

#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "GetFileAttributesW",      (SYSCALL)GetFileAttributesW,      0 },
#else
  { "GetFileAttributesW",      (SYSCALL)0,                       0 },
#endif

#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "GetFileAttributesExW",    (SYSCALL)GetFileAttributesExW,    0 },
#else
  { "GetFileAttributesExW",    (SYSCALL)0,                       0 },
#endif

#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
        LPVOID))aSyscall[22].pCurrent)


  { "GetFileSize",             (SYSCALL)GetFileSize,             0 },




#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)

#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
  { "GetFullPathNameA",        (SYSCALL)GetFullPathNameA,        0 },
#else
  { "GetFullPathNameA",        (SYSCALL)0,                       0 },
#endif

#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
        LPSTR*))aSyscall[24].pCurrent)

#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
  { "GetFullPathNameW",        (SYSCALL)GetFullPathNameW,        0 },
#else
  { "GetFullPathNameW",        (SYSCALL)0,                       0 },
#endif

#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
        LPWSTR*))aSyscall[25].pCurrent)

  { "GetLastError",            (SYSCALL)GetLastError,            0 },

#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)

#if SQLITE_OS_WINCE
  /* The GetProcAddressA() routine is only available on Windows CE. */
  { "GetProcAddressA",         (SYSCALL)GetProcAddressA,         0 },
#else
  /* All other Windows platforms expect GetProcAddress() to take
  ** an ANSI string regardless of the _UNICODE setting */
  { "GetProcAddressA",         (SYSCALL)GetProcAddress,          0 },
#endif

#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
        LPCSTR))aSyscall[27].pCurrent)


  { "GetSystemInfo",           (SYSCALL)GetSystemInfo,           0 },




#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)

  { "GetSystemTime",           (SYSCALL)GetSystemTime,           0 },

#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)

#if !SQLITE_OS_WINCE
  { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
#else
  { "GetSystemTimeAsFileTime", (SYSCALL)0,                       0 },
#endif

#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
        LPFILETIME))aSyscall[30].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "GetTempPathA",            (SYSCALL)GetTempPathA,            0 },
#else
  { "GetTempPathA",            (SYSCALL)0,                       0 },
#endif

#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "GetTempPathW",            (SYSCALL)GetTempPathW,            0 },
#else
  { "GetTempPathW",            (SYSCALL)0,                       0 },
#endif

#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)


  { "GetTickCount",            (SYSCALL)GetTickCount,            0 },




#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "GetVersionExA",           (SYSCALL)GetVersionExA,           0 },
#else
  { "GetVersionExA",           (SYSCALL)0,                       0 },
#endif

#define osGetVersionExA ((BOOL(WINAPI*)( \
        LPOSVERSIONINFOA))aSyscall[34].pCurrent)

  { "HeapAlloc",               (SYSCALL)HeapAlloc,               0 },

#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
        SIZE_T))aSyscall[35].pCurrent)


  { "HeapCreate",              (SYSCALL)HeapCreate,              0 },




#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
        SIZE_T))aSyscall[36].pCurrent)


  { "HeapDestroy",             (SYSCALL)HeapDestroy,             0 },




#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)

  { "HeapFree",                (SYSCALL)HeapFree,                0 },

#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)

  { "HeapReAlloc",             (SYSCALL)HeapReAlloc,             0 },

#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
        SIZE_T))aSyscall[39].pCurrent)

  { "HeapSize",                (SYSCALL)HeapSize,                0 },

#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
        LPCVOID))aSyscall[40].pCurrent)


  { "HeapValidate",            (SYSCALL)HeapValidate,            0 },




#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
        LPCVOID))aSyscall[41].pCurrent)

#if defined(SQLITE_WIN32_HAS_ANSI)
  { "LoadLibraryA",            (SYSCALL)LoadLibraryA,            0 },
#else
  { "LoadLibraryA",            (SYSCALL)0,                       0 },
#endif

#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)

#if defined(SQLITE_WIN32_HAS_WIDE)
  { "LoadLibraryW",            (SYSCALL)LoadLibraryW,            0 },
#else
  { "LoadLibraryW",            (SYSCALL)0,                       0 },
#endif

#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)


  { "LocalFree",               (SYSCALL)LocalFree,               0 },




#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)

#if !SQLITE_OS_WINCE
  { "LockFile",                (SYSCALL)LockFile,                0 },

#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
        DWORD))aSyscall[45].pCurrent)
#else
  { "LockFile",                (SYSCALL)0,                       0 },
#endif






#if !SQLITE_OS_WINCE
  { "LockFileEx",              (SYSCALL)LockFileEx,              0 },

#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
        LPOVERLAPPED))aSyscall[46].pCurrent)
#else
  { "LockFileEx",              (SYSCALL)0,                       0 },
#endif







  { "MapViewOfFile",           (SYSCALL)MapViewOfFile,           0 },




#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
        SIZE_T))aSyscall[47].pCurrent)

  { "MultiByteToWideChar",     (SYSCALL)MultiByteToWideChar,     0 },

#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
        int))aSyscall[48].pCurrent)

  { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },

#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
        LARGE_INTEGER*))aSyscall[49].pCurrent)

  { "ReadFile",                (SYSCALL)ReadFile,                0 },

#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
        LPOVERLAPPED))aSyscall[50].pCurrent)

  { "SetEndOfFile",            (SYSCALL)SetEndOfFile,            0 },

#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)


  { "SetFilePointer",          (SYSCALL)SetFilePointer,          0 },




#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
        DWORD))aSyscall[52].pCurrent)


  { "Sleep",                   (SYSCALL)Sleep,                   0 },




#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)

  { "SystemTimeToFileTime",    (SYSCALL)SystemTimeToFileTime,    0 },

#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
        LPFILETIME))aSyscall[54].pCurrent)

#if !SQLITE_OS_WINCE
  { "UnlockFile",              (SYSCALL)UnlockFile,              0 },

#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
        DWORD))aSyscall[55].pCurrent)
#else
  { "UnlockFile",              (SYSCALL)0,                       0 },
#endif






#if !SQLITE_OS_WINCE
  { "UnlockFileEx",            (SYSCALL)UnlockFileEx,            0 },

#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
        LPOVERLAPPED))aSyscall[56].pCurrent)
#else
  { "UnlockFileEx",            (SYSCALL)0,                       0 },
#endif




  { "UnmapViewOfFile",         (SYSCALL)UnmapViewOfFile,         0 },

#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)

  { "WideCharToMultiByte",     (SYSCALL)WideCharToMultiByte,     0 },

#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
        LPCSTR,LPBOOL))aSyscall[58].pCurrent)

  { "WriteFile",               (SYSCALL)WriteFile,               0 },

#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \









        LPOVERLAPPED))aSyscall[59].pCurrent)














































































































}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
................................................................................
    }
  }
  for(i++; i<ArraySize(aSyscall); i++){
    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
  }
  return 0;
}



























































/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation:  Win95, Win98, and WinME lack
** the LockFileEx() API.  But we can still statically link against that
** API as long as we don't call it when running Win95/98/ME.  A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
#if SQLITE_OS_WINCE
# define isNT()  (1)
#else
  static int isNT(void){
    if( sqlite3_os_type==0 ){
      OSVERSIONINFOA sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
      osGetVersionExA(&sInfo);
................................................................................
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  assert( nBytes>=0 );
  p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  if( !p ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
                nBytes, osGetLastError(), (void*)hHeap);
................................................................................
static void winMemFree(void *pPrior){
  HANDLE hHeap;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
  if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
                pPrior, osGetLastError(), (void*)hHeap);
  }
................................................................................
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  assert( nBytes>=0 );
  if( !pPrior ){
    p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  }else{
    p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
................................................................................
  HANDLE hHeap;
  SIZE_T n;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  if( !p ) return 0;
  n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
  if( n==(SIZE_T)-1 ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
                p, osGetLastError(), (void*)hHeap);
................................................................................
** Initialize this module.
*/
static int winMemInit(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return SQLITE_ERROR;
  assert( pWinMemData->magic==WINMEM_MAGIC );


  if( !pWinMemData->hHeap ){
    pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
                                      SQLITE_WIN32_HEAP_INIT_SIZE,
                                      SQLITE_WIN32_HEAP_MAX_SIZE);
    if( !pWinMemData->hHeap ){
      sqlite3_log(SQLITE_NOMEM,
          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
          osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
          SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
      return SQLITE_NOMEM;
    }
    pWinMemData->bOwned = TRUE;

  }










  assert( pWinMemData->hHeap!=0 );
  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  return SQLITE_OK;
}

/*
** Deinitialize this module.
................................................................................
*/
static void winMemShutdown(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return;
  if( pWinMemData->hHeap ){
    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
    assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
    if( pWinMemData->bOwned ){
      if( !osHeapDestroy(pWinMemData->hHeap) ){
        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
                    osGetLastError(), (void*)pWinMemData->hHeap);
      }
................................................................................
  ** returns the number of TCHARs written to the output
  ** buffer, excluding the terminating null char.
  */
  DWORD dwLen = 0;
  char *zOut = 0;

  if( isNT() ){











    LPWSTR zTempWide = NULL;
    dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                             FORMAT_MESSAGE_FROM_SYSTEM |
                             FORMAT_MESSAGE_IGNORE_INSERTS,
                             NULL,
                             lastErrno,
                             0,
                             (LPWSTR) &zTempWide,
                             0,
                             0);

    if( dwLen > 0 ){
      /* allocate a buffer and convert to UTF8 */
      sqlite3BeginBenignMalloc();
      zOut = unicodeToUtf8(zTempWide);
      sqlite3EndBenignMalloc();

      /* free the system buffer allocated by FormatMessage */
      osLocalFree(zTempWide);

    }
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0


  }else{
    char *zTemp = NULL;
    dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                             FORMAT_MESSAGE_FROM_SYSTEM |
                             FORMAT_MESSAGE_IGNORE_INSERTS,
                             NULL,
                             lastErrno,
                             0,
................................................................................
      /* allocate a buffer and convert to UTF8 */
      sqlite3BeginBenignMalloc();
      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
      sqlite3EndBenignMalloc();
      /* free the system buffer allocated by FormatMessage */
      osLocalFree(zTemp);
    }
#endif
  }

  if( 0 == dwLen ){
    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
  }else{
    /* copy a maximum of nBuf chars to output buffer */
    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
    /* free the UTF8 buffer */
    sqlite3_free(zOut);
................................................................................
      *pError = e;
    }
    return 0;
  }
  if( e==ERROR_ACCESS_DENIED ||
      e==ERROR_LOCK_VIOLATION ||
      e==ERROR_SHARING_VIOLATION ){
    osSleep(win32IoerrRetryDelay*(1+*pnRetry));
    ++*pnRetry;
    return 1;
  }
  if( pError ){
    *pError = e;
  }
  return 0;
................................................................................

/*
** Acquire a lock on the handle h
*/
static void winceMutexAcquire(HANDLE h){
   DWORD dwErr;
   do {
     dwErr = WaitForSingleObject(h, INFINITE);
   } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
}
/*
** Release a lock acquired by winceMutexAcquire()
*/
#define winceMutexRelease(h) ReleaseMutex(h)

................................................................................
  }
}

/* 
** An implementation of the LockFile() API of Windows for CE
*/
static BOOL winceLockFile(
  HANDLE *phFile,
  DWORD dwFileOffsetLow,
  DWORD dwFileOffsetHigh,
  DWORD nNumberOfBytesToLockLow,
  DWORD nNumberOfBytesToLockHigh
){
  winFile *pFile = HANDLE_TO_WINFILE(phFile);
  BOOL bReturn = FALSE;
................................................................................
  return bReturn;
}

/*
** An implementation of the UnlockFile API of Windows for CE
*/
static BOOL winceUnlockFile(
  HANDLE *phFile,
  DWORD dwFileOffsetLow,
  DWORD dwFileOffsetHigh,
  DWORD nNumberOfBytesToUnlockLow,
  DWORD nNumberOfBytesToUnlockHigh
){
  winFile *pFile = HANDLE_TO_WINFILE(phFile);
  BOOL bReturn = FALSE;
................................................................................
      bReturn = TRUE;
    }
  }

  winceMutexRelease(pFile->hMutex);
  return bReturn;
}





/*
** An implementation of the LockFileEx() API of Windows for CE

*/
static BOOL winceLockFileEx(
  HANDLE *phFile,
  DWORD dwFlags,
  DWORD dwReserved,
  DWORD nNumberOfBytesToLockLow,
  DWORD nNumberOfBytesToLockHigh,
  LPOVERLAPPED lpOverlapped



){
  UNUSED_PARAMETER(dwReserved);
  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);


















  /* If the caller wants a shared read lock, forward this call
  ** to winceLockFile */
  if (lpOverlapped->Offset == (DWORD)SHARED_FIRST &&
      dwFlags == 1 &&
      nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
    return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);

  }
  return FALSE;
}
/*
** End of the special code for wince
*****************************************************************************/









#endif /* SQLITE_OS_WINCE */




















/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
******************************************************************************/

/*
................................................................................

/*
** Move the current position of the file handle passed as the first 
** argument to offset iOffset within the file. If successful, return 0. 
** Otherwise, set pFile->lastErrno and return non-zero.
*/
static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){

  LONG upperBits;                 /* Most sig. 32 bits of new offset */
  LONG lowerBits;                 /* Least sig. 32 bits of new offset */
  DWORD dwRet;                    /* Value returned by SetFilePointer() */
  DWORD lastErrno;                /* Value returned by GetLastError() */

  upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
  lowerBits = (LONG)(iOffset & 0xffffffff);
................................................................................
    pFile->lastErrno = lastErrno;
    winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
             "seekWinFile", pFile->zPath);
    return 1;
  }

  return 0;




















}

/*
** Close a file.
**
** It is reported that an attempt to close a handle might sometimes
** fail.  This is a very unreasonable result, but Windows is notorious
................................................................................

  assert( id!=0 );
  assert( pFile->pShm==0 );
  OSTRACE(("CLOSE %d\n", pFile->h));
  do{
    rc = osCloseHandle(pFile->h);
    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (osSleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
  winceDestroyLock(pFile);
  if( pFile->zDeleteOnClose ){
    int cnt = 0;
    while(
           osDeleteFileW(pFile->zDeleteOnClose)==0
        && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 
        && cnt++ < WINCE_DELETION_ATTEMPTS
    ){
       osSleep(100);  /* Wait a little before trying again */
    }
    sqlite3_free(pFile->zDeleteOnClose);
  }
#endif
  OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
  if( rc ){
    pFile->h = NULL;
................................................................................
#endif
}

/*
** Determine the current size of a file in bytes
*/
static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
  DWORD upperBits;
  DWORD lowerBits;
  winFile *pFile = (winFile*)id;
  DWORD lastErrno;


  assert( id!=0 );
  SimulateIOError(return SQLITE_IOERR_FSTAT);


















  lowerBits = osGetFileSize(pFile->h, &upperBits);

  if(   (lowerBits == INVALID_FILE_SIZE)
     && ((lastErrno = osGetLastError())!=NO_ERROR) )
  {
    pFile->lastErrno = lastErrno;
    return winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
             "winFileSize", pFile->zPath);
  }
  *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;


  return SQLITE_OK;
}

/*
** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
*/
#ifndef LOCKFILE_FAIL_IMMEDIATELY
# define LOCKFILE_FAIL_IMMEDIATELY 1
#endif

























/*
** Acquire a reader lock.
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
static int getReadLock(winFile *pFile){
  int res;
  if( isNT() ){
    OVERLAPPED ovlp;
    ovlp.Offset = SHARED_FIRST;
    ovlp.OffsetHigh = 0;
    ovlp.hEvent = 0;
    res = osLockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
                       0, SHARED_SIZE, 0, &ovlp);
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 



*/



#if SQLITE_OS_WINCE==0



  }else{
    int lk;
    sqlite3_randomness(sizeof(lk), &lk);
    pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));

    res = osLockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
#endif
  }

  if( res == 0 ){
    pFile->lastErrno = osGetLastError();
    /* No need to log a failure to lock */
  }
  return res;
}

................................................................................
/*
** Undo a readlock
*/
static int unlockReadLock(winFile *pFile){
  int res;
  DWORD lastErrno;
  if( isNT() ){
    res = osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
*/
#if SQLITE_OS_WINCE==0


  }else{
    res = osUnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
#endif

  }

  if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
    pFile->lastErrno = lastErrno;
    winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
             "unlockReadLock", pFile->zPath);
  }
  return res;
}
................................................................................
  */
  newLocktype = pFile->locktype;
  if(   (pFile->locktype==NO_LOCK)
     || (   (locktype==EXCLUSIVE_LOCK)
         && (pFile->locktype==RESERVED_LOCK))
  ){
    int cnt = 3;

    while( cnt-->0 && (res = osLockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
      /* Try 3 times to get the pending lock.  This is needed to work
      ** around problems caused by indexing and/or anti-virus software on
      ** Windows systems.
      ** If you are using this code as a model for alternative VFSes, do not
      ** copy this retry logic.  It is a hack intended for Windows only.
      */
      OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
      if( cnt ) osSleep(1);
    }
    gotPendingLock = res;
    if( !res ){
      lastErrno = osGetLastError();
    }
  }

................................................................................
    }
  }

  /* Acquire a RESERVED lock
  */
  if( locktype==RESERVED_LOCK && res ){
    assert( pFile->locktype==SHARED_LOCK );
    res = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
    if( res ){
      newLocktype = RESERVED_LOCK;
    }else{
      lastErrno = osGetLastError();
    }
  }

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

  /* Acquire an EXCLUSIVE lock
  */
  if( locktype==EXCLUSIVE_LOCK && res ){
    assert( pFile->locktype>=SHARED_LOCK );
    res = unlockReadLock(pFile);
    OSTRACE(("unreadlock = %d\n", res));

    res = osLockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
    if( res ){
      newLocktype = EXCLUSIVE_LOCK;
    }else{
      lastErrno = osGetLastError();
      OSTRACE(("error-code = %d\n", lastErrno));
      getReadLock(pFile);
    }
  }

  /* If we are holding a PENDING lock that ought to be released, then
  ** release it now.
  */
  if( gotPendingLock && locktype==SHARED_LOCK ){
    osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
  }

  /* Update the state of the lock has held in the file descriptor then
  ** return the appropriate result code.
  */
  if( res ){
    rc = SQLITE_OK;
................................................................................
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  assert( id!=0 );
  if( pFile->locktype>=RESERVED_LOCK ){
    rc = 1;
    OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
  }else{
    rc = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
    if( rc ){
      osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
    }
    rc = !rc;
    OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
  }
  *pResOut = rc;
  return SQLITE_OK;
}
................................................................................
  int rc = SQLITE_OK;
  assert( pFile!=0 );
  assert( locktype<=SHARED_LOCK );
  OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
          pFile->locktype, pFile->sharedLockByte));
  type = pFile->locktype;
  if( type>=EXCLUSIVE_LOCK ){
    osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
      /* This should never happen.  We should always be able to
      ** reacquire the read lock */
      rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
               "winUnlock", pFile->zPath);
    }
  }
  if( type>=RESERVED_LOCK ){
    osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
  }
  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
    unlockReadLock(pFile);
  }
  if( type>=PENDING_LOCK ){
    osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
  }
  pFile->locktype = (u8)locktype;
  return rc;
}

/*
** If *pArg is inititially negative then this is a query.  Set *pArg to
................................................................................
#define _SHM_WRLCK  3
static int winShmSystemLock(
  winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
  int ofst,             /* Offset to first byte to be locked/unlocked */
  int nByte             /* Number of bytes to lock or unlock */
){
  OVERLAPPED ovlp;
  DWORD dwFlags;
  int rc = 0;           /* Result code form Lock/UnlockFileEx() */

  /* Access to the winShmNode object is serialized by the caller */
  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );

  /* Initialize the locking parameters */
  dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;

  memset(&ovlp, 0, sizeof(OVERLAPPED));
  ovlp.Offset = ofst;

  /* Release/Acquire the system-level lock */
  if( lockType==_SHM_UNLCK ){
    rc = osUnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);

  }else{



    rc = osLockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
  }
  
  if( rc!= 0 ){
    rc = SQLITE_OK;
  }else{
    pFile->lastErrno =  osGetLastError();
    rc = SQLITE_BUSY;
................................................................................
    }
    pShmNode->aRegion = apNew;

    while( pShmNode->nRegion<=iRegion ){
      HANDLE hMap;                /* file-mapping handle */
      void *pMap = 0;             /* Mapped memory region */
     





      hMap = osCreateFileMapping(pShmNode->hFile.h, 
          NULL, PAGE_READWRITE, 0, nByte, NULL
      );

      OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
               (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
               hMap ? "ok" : "failed"));
      if( hMap ){
        int iOffset = pShmNode->nRegion*szRegion;
        int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;





        pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
            0, iOffset - iOffsetShift, szRegion + iOffsetShift
        );

        OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
                 (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
                 szRegion, pMap ? "ok" : "failed"));
      }
      if( !pMap ){
        pShmNode->lastErrno = osGetLastError();
        rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
................................................................................
** is obtained from malloc and must be freed by the calling
** function.
*/
static void *convertUtf8Filename(const char *zFilename){
  void *zConverted = 0;
  if( isNT() ){
    zConverted = utf8ToUnicode(zFilename);
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
*/
#if SQLITE_OS_WINCE==0


  }else{
    zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
#endif
  }

  /* caller will handle out of memory */
  return zConverted;
}

/*
** Create a temporary file name in zBuf.  zBuf must be big enough to
** hold at pVfs->mxPathname characters.
................................................................................
*/
static int getTempname(int nBuf, char *zBuf){
  static char zChars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789";
  size_t i, j;

  char zTempPath[MAX_PATH+2];

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. 
  */
  SimulateIOError( return SQLITE_IOERR );



  if( sqlite3_temp_directory ){
    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);


  }else if( isNT() ){
    char *zMulti;
    WCHAR zWidePath[MAX_PATH];
    osGetTempPathW(MAX_PATH-30, zWidePath);
    zMulti = unicodeToUtf8(zWidePath);
    if( zMulti ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
      sqlite3_free(zMulti);
    }else{
      return SQLITE_IOERR_NOMEM;
    }
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 

** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    char *zUtf8;
    char zMbcsPath[MAX_PATH];
    osGetTempPathA(MAX_PATH-30, zMbcsPath);
    zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
    if( zUtf8 ){
      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
      sqlite3_free(zUtf8);
    }else{
      return SQLITE_IOERR_NOMEM;
    }
#endif
  }



  /* Check that the output buffer is large enough for the temporary file 
  ** name. If it is not, return SQLITE_ERROR.
  */


  if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
    return SQLITE_ERROR;
  }

  for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
  zTempPath[i] = 0;

  sqlite3_snprintf(nBuf-18, zBuf,
                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);

  j = sqlite3Strlen30(zBuf);
  sqlite3_randomness(15, &zBuf[j]);
  for(i=0; i<15; i++, j++){
    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  }
  zBuf[j] = 0;
  zBuf[j+1] = 0;

  OSTRACE(("TEMP FILENAME: %s\n", zBuf));
  return SQLITE_OK; 
}






























/*
** Open a file.
*/
static int winOpen(
  sqlite3_vfs *pVfs,        /* Not used */
  const char *zName,        /* Name of the file (UTF-8) */
................................................................................
        zUtf8Name[strlen(zUtf8Name)+1]==0 );

  /* Convert the filename to the system encoding. */
  zConverted = convertUtf8Filename(zUtf8Name);
  if( zConverted==0 ){
    return SQLITE_IOERR_NOMEM;
  }






  if( isReadWrite ){
    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  }else{
    dwDesiredAccess = GENERIC_READ;
  }

................................................................................
  /* Reports from the internet are that performance is always
  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
#if SQLITE_OS_WINCE
  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif

  if( isNT() ){


















    while( (h = osCreateFileW((LPCWSTR)zConverted,
                              dwDesiredAccess,
                              dwShareMode, NULL,
                              dwCreationDisposition,
                              dwFlagsAndAttributes,
                              NULL))==INVALID_HANDLE_VALUE &&
                              retryIoerr(&cnt, &lastErrno) ){}
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ANSI version of these Windows API do not exist for WINCE,

** it's important to not reference them for WINCE builds.
*/

#if SQLITE_OS_WINCE==0
  }else{
    while( (h = osCreateFileA((LPCSTR)zConverted,
                              dwDesiredAccess,
                              dwShareMode, NULL,
                              dwCreationDisposition,
                              dwFlagsAndAttributes,
                              NULL))==INVALID_HANDLE_VALUE &&
                              retryIoerr(&cnt, &lastErrno) ){}
#endif

  }


  logIoerr(cnt);

  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));

  if( h==INVALID_HANDLE_VALUE ){
................................................................................
static int winDelete(
  sqlite3_vfs *pVfs,          /* Not used on win32 */
  const char *zFilename,      /* Name of file to delete */
  int syncDir                 /* Not used on win32 */
){
  int cnt = 0;
  int rc;

  DWORD lastErrno;
  void *zConverted;
  UNUSED_PARAMETER(pVfs);
  UNUSED_PARAMETER(syncDir);

  SimulateIOError(return SQLITE_IOERR_DELETE);
  zConverted = convertUtf8Filename(zFilename);
  if( zConverted==0 ){
    return SQLITE_IOERR_NOMEM;
  }
  if( isNT() ){
    rc = 1;











    while( osGetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&













         (rc = osDeleteFileW(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
    rc = rc ? SQLITE_OK : SQLITE_ERROR;
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0






  }else{
    rc = 1;

    while( osGetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&












         (rc = osDeleteFileA(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
    rc = rc ? SQLITE_OK : SQLITE_ERROR;
#endif


  }



  if( rc ){
    rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
             "winDelete", zFilename);
  }else{
    logIoerr(cnt);
  }
  sqlite3_free(zConverted);
................................................................................
        winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
        sqlite3_free(zConverted);
        return SQLITE_IOERR_ACCESS;
      }else{
        attr = INVALID_FILE_ATTRIBUTES;
      }
    }
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 

** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    attr = osGetFileAttributesA((char*)zConverted);
#endif
  }

  sqlite3_free(zConverted);
  switch( flags ){
    case SQLITE_ACCESS_READ:
    case SQLITE_ACCESS_EXISTS:
      rc = attr!=INVALID_FILE_ATTRIBUTES;
      break;
    case SQLITE_ACCESS_READWRITE:
................................................................................
    default:
      assert(!"Invalid flags argument");
  }
  *pResOut = rc;
  return SQLITE_OK;
}







































/*
** Turn a relative pathname into a full pathname.  Write the full
** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
static int winFullPathname(
................................................................................
  int nFull,                    /* Size of output buffer in bytes */
  char *zFull                   /* Output buffer */
){
  
#if defined(__CYGWIN__)
  SimulateIOError( return SQLITE_ERROR );
  UNUSED_PARAMETER(nFull);




















  cygwin_conv_to_full_win32_path(zRelative, zFull);

  return SQLITE_OK;
#endif

#if SQLITE_OS_WINCE
  SimulateIOError( return SQLITE_ERROR );
  UNUSED_PARAMETER(nFull);
  /* WinCE has no concept of a relative pathname, or so I am told. */











  sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);

  return SQLITE_OK;
#endif

#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
  int nByte;
  void *zConverted;
  char *zOut;

  /* If this path name begins with "/X:", where "X" is any alphabetic
  ** character, discard the initial "/" from the pathname.
  */
................................................................................

  /* It's odd to simulate an io-error here, but really this is just
  ** using the io-error infrastructure to test that SQLite handles this
  ** function failing. This function could fail if, for example, the
  ** current working directory has been unlinked.
  */
  SimulateIOError( return SQLITE_ERROR );
  UNUSED_PARAMETER(nFull);










  zConverted = convertUtf8Filename(zRelative);
  if( zConverted==0 ){
    return SQLITE_IOERR_NOMEM;
  }
  if( isNT() ){
    LPWSTR zTemp;
    nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0) + 3;
................................................................................
      sqlite3_free(zConverted);
      return SQLITE_IOERR_NOMEM;
    }
    osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
    sqlite3_free(zConverted);
    zOut = unicodeToUtf8(zTemp);
    sqlite3_free(zTemp);
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 

** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    char *zTemp;
    nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
    zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
    if( zTemp==0 ){
      sqlite3_free(zConverted);
      return SQLITE_IOERR_NOMEM;
    }
    osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
    sqlite3_free(zConverted);
    zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
    sqlite3_free(zTemp);
#endif
  }

  if( zOut ){
    sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
    sqlite3_free(zOut);
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR_NOMEM;
  }
#endif
}
................................................................................
  HANDLE h;
  void *zConverted = convertUtf8Filename(zFilename);
  UNUSED_PARAMETER(pVfs);
  if( zConverted==0 ){
    return 0;
  }
  if( isNT() ){
    h = osLoadLibraryW((LPCWSTR)zConverted);
/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 
** Since the ANSI version of these Windows API do not exist for WINCE,
** it's important to not reference them for WINCE builds.
*/
#if SQLITE_OS_WINCE==0
  }else{
    h = osLoadLibraryA((char*)zConverted);
#endif
  }

  sqlite3_free(zConverted);
  return (void*)h;
}
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
  UNUSED_PARAMETER(pVfs);
  getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
................................................................................
    n += sizeof(x);
  }
  if( sizeof(DWORD)<=nBuf-n ){
    DWORD pid = osGetCurrentProcessId();
    memcpy(&zBuf[n], &pid, sizeof(pid));
    n += sizeof(pid);
  }







  if( sizeof(DWORD)<=nBuf-n ){
    DWORD cnt = osGetTickCount();
    memcpy(&zBuf[n], &cnt, sizeof(cnt));
    n += sizeof(cnt);
  }

  if( sizeof(LARGE_INTEGER)<=nBuf-n ){
    LARGE_INTEGER i;
    osQueryPerformanceCounter(&i);
    memcpy(&zBuf[n], &i, sizeof(i));
    n += sizeof(i);
  }
#endif
................................................................................
}


/*
** Sleep for a little while.  Return the amount of time slept.
*/
static int winSleep(sqlite3_vfs *pVfs, int microsec){
  osSleep((microsec+999)/1000);
  UNUSED_PARAMETER(pVfs);
  return ((microsec+999)/1000)*1000;
}

/*
** The following variable, if set to a non-zero value, is interpreted as
** the number of seconds since 1970 and is used to set the result of
................................................................................
    winSetSystemCall,    /* xSetSystemCall */
    winGetSystemCall,    /* xGetSystemCall */
    winNextSystemCall,   /* xNextSystemCall */
  };

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==60 );

#ifndef SQLITE_OMIT_WAL
  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));



  osGetSystemInfo(&winSysInfo);

  assert(winSysInfo.dwAllocationGranularity > 0);
#endif

  sqlite3_vfs_register(&winVfs, 1);
  return SQLITE_OK; 
}

SQLITE_API int sqlite3_os_end(void){ 






  return SQLITE_OK;
}

#endif /* SQLITE_OS_WIN */

/************** End of os_win.c **********************************************/
/************** Begin file bitvec.c ******************************************/
................................................................................
    sqlite3_mutex_leave(pcache1.mutex);
  }
  if( p==0 ){
    /* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool.  Get
    ** it from sqlite3Malloc instead.
    */
    p = sqlite3Malloc(nByte);

    if( p ){
      int sz = sqlite3MallocSize(p);
      sqlite3_mutex_enter(pcache1.mutex);
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
      sqlite3_mutex_leave(pcache1.mutex);
    }

    sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
  }
  return p;
}

/*
** Free an allocated buffer obtained from pcache1Alloc().
................................................................................
    pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
    assert( pcache1.nFreeSlot<=pcache1.nSlot );
    sqlite3_mutex_leave(pcache1.mutex);
  }else{
    assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
    sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
    nFreed = sqlite3MallocSize(p);

    sqlite3_mutex_enter(pcache1.mutex);
    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
    sqlite3_mutex_leave(pcache1.mutex);

    sqlite3_free(p);
  }
  return nFreed;
}

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
................................................................................
    /* If a WAL transaction is being committed, there is no point in writing
    ** any pages with page numbers greater than nTruncate into the WAL file.
    ** They will never be read by any client. So remove them from the pDirty
    ** list here. */
    PgHdr *p;
    PgHdr **ppNext = &pList;
    nList = 0;
    for(p=pList; (*ppNext = p); p=p->pDirty){
      if( p->pgno<=nTruncate ){
        ppNext = &p->pDirty;
        nList++;
      }
    }
    assert( pList );
  }else{
................................................................................

  /* Set the output variable to NULL in case an error occurs. */
  *ppPager = 0;

#ifndef SQLITE_OMIT_MEMORYDB
  if( flags & PAGER_MEMORY ){
    memDb = 1;




    zFilename = 0;

  }
#endif

  /* Compute and store the full pathname in an allocated buffer pointed
  ** to by zPathname, length nPathname. Or, if this is a temporary file,
  ** leave both nPathname and zPathname set to 0.
  */
  if( zFilename && zFilename[0] ){
    const char *z;
    nPathname = pVfs->mxPathname+1;
    zPathname = sqlite3Malloc(nPathname*2);
    if( zPathname==0 ){
      return SQLITE_NOMEM;
    }
    zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
    rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
    nPathname = sqlite3Strlen30(zPathname);
    z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
................................................................................
      ** bytes in length. This means the database cannot be opened,
      ** as it will not be possible to open the journal file or even
      ** check for a hot-journal before reading.
      */
      rc = SQLITE_CANTOPEN_BKPT;
    }
    if( rc!=SQLITE_OK ){
      sqlite3_free(zPathname);
      return rc;
    }
  }

  /* Allocate memory for the Pager structure, PCache object, the
  ** three file descriptors, the database file name and the journal 
  ** file name. The layout in memory is as follows:
................................................................................
    nPathname + 8 + 2              /* zJournal */
#ifndef SQLITE_OMIT_WAL
    + nPathname + 4 + 2            /* zWal */
#endif
  );
  assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
  if( !pPtr ){
    sqlite3_free(zPathname);
    return SQLITE_NOMEM;
  }
  pPager =              (Pager*)(pPtr);
  pPager->pPCache =    (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
  pPager->fd =   (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
  pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
  pPager->jfd =  (sqlite3_file*)(pPtr += journalFileSize);
................................................................................
  assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );

  /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
  if( zPathname ){
    assert( nPathname>0 );
    pPager->zJournal =   (char*)(pPtr += nPathname + 1 + nUri);
    memcpy(pPager->zFilename, zPathname, nPathname);
    memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
    memcpy(pPager->zJournal, zPathname, nPathname);
    memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
    sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
#ifndef SQLITE_OMIT_WAL
    pPager->zWal = &pPager->zJournal[nPathname+8+1];
    memcpy(pPager->zWal, zPathname, nPathname);
    memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
    sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
#endif
    sqlite3_free(zPathname);
  }
  pPager->pVfs = pVfs;
  pPager->vfsFlags = vfsFlags;

  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
................................................................................
  }

  return rc;
}

/*
** Return the full pathname of the database file.







*/
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager){
  return pPager->zFilename;
}

/*
** Return the VFS structure for the pager.
*/
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){
  return pPager->pVfs;
................................................................................
  /* Set the variable isMemdb to true for an in-memory database, or 
  ** false for a file-based database.
  */
#ifdef SQLITE_OMIT_MEMORYDB
  const int isMemdb = 0;
#else
  const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
                       || (isTempDb && sqlite3TempInMemory(db));

#endif

  assert( db!=0 );
  assert( pVfs!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( (flags&0xff)==flags );   /* flags fit in 8 bits */

................................................................................
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
  /*
  ** If this Btree is a candidate for shared cache, try to find an
  ** existing BtShared object that we can share with
  */
  if( isMemdb==0 && isTempDb==0 ){
    if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
      int nFullPathname = pVfs->mxPathname+1;
      char *zFullPathname = sqlite3Malloc(nFullPathname);
      MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
      p->sharable = 1;
      if( !zFullPathname ){
        sqlite3_free(p);
        return SQLITE_NOMEM;
      }



      rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);

      if( rc ){
        sqlite3_free(zFullPathname);
        sqlite3_free(p);
        return rc;

      }
#if SQLITE_THREADSAFE
      mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
      sqlite3_mutex_enter(mutexOpen);
      mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
      sqlite3_mutex_enter(mutexShared);
#endif
      for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
        assert( pBt->nRef>0 );
        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){
          int iDb;
          for(iDb=db->nDb-1; iDb>=0; iDb--){
            Btree *pExisting = db->aDb[iDb].pBt;
            if( pExisting && pExisting->pBt==pBt ){
              sqlite3_mutex_leave(mutexShared);
              sqlite3_mutex_leave(mutexOpen);
................................................................................
  *pnErr = sCheck.nErr;
  if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
  return sqlite3StrAccumFinish(&sCheck.errMsg);
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/*
** Return the full pathname of the underlying database file.

**
** The pager filename is invariant as long as the pager is
** open so it is safe to access without the BtShared mutex.
*/
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){
  assert( p->pBt->pPager!=0 );
  return sqlite3PagerFilename(p->pBt->pPager);
}

/*
** Return the pathname of the journal file for this database. The return
** value of this routine is the same regardless of whether the journal file
** has been created or not.
**
................................................................................
    ** the case where the source and destination databases have the
    ** same schema version.
    */
    if( rc==SQLITE_DONE ){
      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
      if( rc==SQLITE_OK ){
        if( p->pDestDb ){
          sqlite3ResetInternalSchema(p->pDestDb, -1);
        }
        if( destMode==PAGER_JOURNALMODE_WAL ){
          rc = sqlite3BtreeSetVersion(p->pDest, 2);
        }
      }
      if( rc==SQLITE_OK ){
        int nDestTruncate;
................................................................................
}

/*
** Release all resources associated with an sqlite3_backup* handle.
*/
SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
  sqlite3_backup **pp;                 /* Ptr to head of pagers backup list */
  MUTEX_LOGIC( sqlite3_mutex *mutex; ) /* Mutex to protect source database */
  int rc;                              /* Value to return */

  /* Enter the mutexes */
  if( p==0 ) return SQLITE_OK;
  sqlite3_mutex_enter(p->pSrcDb->mutex);
  sqlite3BtreeEnter(p->pSrc);
  MUTEX_LOGIC( mutex = p->pSrcDb->mutex; )
  if( p->pDestDb ){
    sqlite3_mutex_enter(p->pDestDb->mutex);
  }

  /* Detach this backup from the source pager. */
  if( p->pDestDb ){
    p->pSrc->nBackup--;
................................................................................

  /* Set the error code of the destination database handle. */
  rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
  sqlite3Error(p->pDestDb, rc, 0);

  /* Exit the mutexes and free the backup context structure. */
  if( p->pDestDb ){
    sqlite3_mutex_leave(p->pDestDb->mutex);
  }
  sqlite3BtreeLeave(p->pSrc);
  if( p->pDestDb ){
    /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
    ** call to sqlite3_backup_init() and is destroyed by a call to
    ** sqlite3_backup_finish(). */
    sqlite3_free(p);
  }
  sqlite3_mutex_leave(mutex);
  return rc;
}

/*
** Return the number of pages still to be backed up as of the most recent
** call to sqlite3_backup_step().
*/
................................................................................
** Delete an entire VDBE.
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
  sqlite3 *db;

  if( NEVER(p==0) ) return;
  db = p->db;

  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
  }else{
    assert( db->pVdbe==p );
    db->pVdbe = p->pNext;
  }
  if( p->pNext ){
................................................................................
  if( pStmt==0 ){
    /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
    ** pointer is a harmless no-op. */
    rc = SQLITE_OK;
  }else{
    Vdbe *v = (Vdbe*)pStmt;
    sqlite3 *db = v->db;
#if SQLITE_THREADSAFE
    sqlite3_mutex *mutex;
#endif
    if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
#if SQLITE_THREADSAFE
    mutex = v->db->mutex;
#endif
    sqlite3_mutex_enter(mutex);
    rc = sqlite3VdbeFinalize(v);
    rc = sqlite3ApiExit(db, rc);
    sqlite3_mutex_leave(mutex);

  }
  return rc;
}

/*
** Terminate the current execution of an SQL statement and reset it
** back to its starting state so that it can be reused. A success code from
................................................................................
#if defined(SQLITE_ENABLE_TREE_EXPLAIN)

/*
** Allocate a new Explain object
*/
SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){
  if( pVdbe ){

    sqlite3BeginBenignMalloc();
    Explain *p = sqlite3_malloc( sizeof(Explain) );
    if( p ){
      memset(p, 0, sizeof(*p));
      p->pVdbe = pVdbe;
      sqlite3_free(pVdbe->pExplain);
      pVdbe->pExplain = p;
      sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase),
                          SQLITE_MAX_LENGTH);
................................................................................
          rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
          if( rc!=SQLITE_OK ){
            goto abort_due_to_error;
          }
        }
        if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
          sqlite3ExpirePreparedStatements(db);
          sqlite3ResetInternalSchema(db, -1);
          db->flags = (db->flags | SQLITE_InternChanges);
        }
      }

      /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
      ** savepoints nested inside of the savepoint being operated on. */
      while( db->pSavepoint!=u.ar.pSavepoint ){
................................................................................
    ** prepared queries. If such a query is out-of-date, we do not want to
    ** discard the database schema, as the user code implementing the
    ** v-table would have to be ready for the sqlite3_vtab structure itself
    ** to be invalidated whenever sqlite3_step() is called from within
    ** a v-table method.
    */
    if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
      sqlite3ResetInternalSchema(db, pOp->p1);
    }

    p->expired = 1;
    rc = SQLITE_SCHEMA;
  }
  break;
}
................................................................................
  u.bl.pC = p->apCsr[pOp->p1];
  assert( u.bl.pC->isSorter==0 );
  assert( u.bl.pC->isTable || pOp->opcode!=OP_RowData );
  assert( u.bl.pC->isIndex || pOp->opcode==OP_RowData );
  assert( u.bl.pC!=0 );
  assert( u.bl.pC->nullRow==0 );
  assert( u.bl.pC->pseudoTableReg==0 );
  assert( !u.bl.pC->isSorter );
  assert( u.bl.pC->pCursor!=0 );
  u.bl.pCrsr = u.bl.pC->pCursor;
  assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) );

  /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
  ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
  ** the cursor.  Hence the following sqlite3VdbeCursorMoveto() call is always
................................................................................
      assert( !db->mallocFailed );
      rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
      if( rc==SQLITE_OK ) rc = u.by.initData.rc;
      sqlite3DbFree(db, u.by.zSql);
      db->init.busy = 0;
    }
  }
  if( rc ) sqlite3ResetInternalSchema(db, -1);
  if( rc==SQLITE_NOMEM ){
    goto no_mem;
  }
  break;
}

#if !defined(SQLITE_OMIT_ANALYZE)
................................................................................
  u.ci.pBt = db->aDb[pOp->p1].pBt;
  u.ci.pPager = sqlite3BtreePager(u.ci.pBt);
  u.ci.eOld = sqlite3PagerGetJournalMode(u.ci.pPager);
  if( u.ci.eNew==PAGER_JOURNALMODE_QUERY ) u.ci.eNew = u.ci.eOld;
  if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld;

#ifndef SQLITE_OMIT_WAL
  u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory
  */
  if( u.ci.eNew==PAGER_JOURNALMODE_WAL
   && (sqlite3Strlen30(u.ci.zFilename)==0           /* Temp file */
       || !sqlite3PagerWalSupported(u.ci.pPager))   /* No shared-memory support */
................................................................................
  testcase( sqlite3GlobalConfig.xLog!=0 );
  sqlite3_log(rc, "statement aborts at %d: [%s] %s", 
                   pc, p->zSql, p->zErrMsg);
  sqlite3VdbeHalt(p);
  if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
  rc = SQLITE_ERROR;
  if( resetSchemaOnFault>0 ){
    sqlite3ResetInternalSchema(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:
  db->lastRowid = lastRowid;
................................................................................
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
          assert( pExpr->x.pSelect==0 );
          pOrig = pEList->a[j].pExpr;
          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
            sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
            return WRC_Abort;
          }
          resolveAlias(pParse, pEList, j, pExpr, "");
          cnt = 1;
          pMatch = 0;
          assert( zTab==0 && zDb==0 );
................................................................................
            pNC->nErr++;
          }
          pExpr->op = TK_NULL;
          return WRC_Prune;
        }
      }
#endif
      if( is_agg && !pNC->allowAgg ){
        sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
        pNC->nErr++;
        is_agg = 0;
      }else if( no_such_func ){
        sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
        pNC->nErr++;
      }else if( wrong_num_args ){
        sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
             nId, zId);
        pNC->nErr++;
      }
      if( is_agg ){
        pExpr->op = TK_AGG_FUNCTION;
        pNC->hasAgg = 1;
      }
      if( is_agg ) pNC->allowAgg = 0;
      sqlite3WalkExprList(pWalker, pList);
      if( is_agg ) pNC->allowAgg = 1;
      /* FIX ME:  Compute pExpr->affinity based on the expected return
      ** type of the function 
      */
      return WRC_Prune;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_SELECT:
................................................................................
    case TK_EXISTS:  testcase( pExpr->op==TK_EXISTS );
#endif
    case TK_IN: {
      testcase( pExpr->op==TK_IN );
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        int nRef = pNC->nRef;
#ifndef SQLITE_OMIT_CHECK
        if( pNC->isCheck ){
          sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
        }
#endif
        sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
        assert( pNC->nRef>=nRef );
        if( nRef!=pNC->nRef ){
          ExprSetProperty(pExpr, EP_VarSelect);
        }
      }
      break;
    }
#ifndef SQLITE_OMIT_CHECK
    case TK_VARIABLE: {
      if( pNC->isCheck ){
        sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
      }
      break;
    }
#endif
  }
  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
................................................................................

  /* Resolve all names in the ORDER BY term expression
  */
  memset(&nc, 0, sizeof(nc));
  nc.pParse = pParse;
  nc.pSrcList = pSelect->pSrc;
  nc.pEList = pEList;
  nc.allowAgg = 1;
  nc.nErr = 0;
  db = pParse->db;
  savedSuppErr = db->suppressErr;
  db->suppressErr = 1;
  rc = sqlite3ResolveExprNames(&nc, pE);
  db->suppressErr = savedSuppErr;
  if( rc ) return 0;
................................................................................
*/
static int resolveOrderGroupBy(
  NameContext *pNC,     /* The name context of the SELECT statement */
  Select *pSelect,      /* The SELECT statement holding pOrderBy */
  ExprList *pOrderBy,   /* An ORDER BY or GROUP BY clause to resolve */
  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
){
  int i;                         /* Loop counter */
  int iCol;                      /* Column number */
  struct ExprList_item *pItem;   /* A term of the ORDER BY clause */
  Parse *pParse;                 /* Parsing context */
  int nResult;                   /* Number of terms in the result set */

  if( pOrderBy==0 ) return 0;
  nResult = pSelect->pEList->nExpr;
................................................................................
      continue;
    }

    /* Otherwise, treat the ORDER BY term as an ordinary expression */
    pItem->iOrderByCol = 0;
    if( sqlite3ResolveExprNames(pNC, pE) ){
      return 1;





    }
  }
  return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
}

/*
** Resolve names in the SELECT statement p and all of its descendents.
................................................................................
        sqlite3ResolveExprNames(&sNC, p->pOffset) ){
      return WRC_Abort;
    }
  
    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
    ** resolve the result-set expression list.
    */
    sNC.allowAgg = 1;
    sNC.pSrcList = p->pSrc;
    sNC.pNext = pOuterNC;
  
    /* Resolve names in the result set. */
    pEList = p->pEList;
    assert( pEList!=0 );
    for(i=0; i<pEList->nExpr; i++){
................................................................................
    }
  
    /* If there are no aggregate functions in the result-set, and no GROUP BY 
    ** expression, do not allow aggregates in any of the other expressions.
    */
    assert( (p->selFlags & SF_Aggregate)==0 );
    pGroupBy = p->pGroupBy;
    if( pGroupBy || sNC.hasAgg ){
      p->selFlags |= SF_Aggregate;
    }else{
      sNC.allowAgg = 0;
    }
  
    /* If a HAVING clause is present, then there must be a GROUP BY clause.
    */
    if( p->pHaving && !pGroupBy ){
      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
      return WRC_Abort;
................................................................................
      return WRC_Abort;
    }

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.allowAgg = 1;

    /* Process the ORDER BY clause for singleton SELECT statements.
    ** The ORDER BY clause for compounds SELECT statements is handled
    ** below, after all of the result-sets for all of the elements of
    ** the compound have been resolved.
    */
    if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
................................................................................
**
** The "x" term of the order by is replaced by "a+b" to render:
**
**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
**
** Function calls are checked to make sure that the function is 
** defined and that the correct number of arguments are specified.
** If the function is an aggregate function, then the pNC->hasAgg is
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
** If an expression contains aggregate functions then the EP_Agg
** property on the expression is set.
**
** An error message is left in pParse if anything is amiss.  The number
** if errors is returned.
*/
SQLITE_PRIVATE int sqlite3ResolveExprNames( 
  NameContext *pNC,       /* Namespace to resolve expressions in. */
  Expr *pExpr             /* The expression to be analyzed. */
){
  int savedHasAgg;
  Walker w;

  if( pExpr==0 ) return 0;
#if SQLITE_MAX_EXPR_DEPTH>0
  {
    Parse *pParse = pNC->pParse;
    if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
      return 1;
    }
    pParse->nHeight += pExpr->nHeight;
  }
#endif
  savedHasAgg = pNC->hasAgg;
  pNC->hasAgg = 0;
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = resolveSelectStep;
  w.pParse = pNC->pParse;
  w.u.pNC = pNC;
  sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
  pNC->pParse->nHeight -= pExpr->nHeight;
#endif
  if( pNC->nErr>0 || w.pParse->nErr>0 ){
    ExprSetProperty(pExpr, EP_Error);
  }
  if( pNC->hasAgg ){
    ExprSetProperty(pExpr, EP_Agg);
  }else if( savedHasAgg ){
    pNC->hasAgg = 1;
  }
  return ExprHasProperty(pExpr, EP_Error);
}


/*
** Resolve all names in all expressions of a SELECT and in all
................................................................................
  if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
  if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
  if( ExprHasProperty(pA, EP_IntValue) ){
    if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
      return 2;
    }
  }else if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
    if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
      return 2;
    }
  }
  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
................................................................................
            break;
          } /* endif pExpr->iTable==pItem->iCursor */
        } /* end loop over pSrcList */
      }
      return WRC_Prune;
    }
    case TK_AGG_FUNCTION: {

      if( !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) ){

        /* Check to see if pExpr is a duplicate of another aggregate 
        ** function that is already in the pAggInfo structure
        */
        struct AggInfo_func *pItem = pAggInfo->aFunc;
        for(i=0; i<pAggInfo->nFunc; i++, pItem++){
          if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
            break;
................................................................................
        }
        /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
        */
        assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
        ExprSetIrreducible(pExpr);
        pExpr->iAgg = (i16)i;
        pExpr->pAggInfo = pAggInfo;
        return WRC_Prune;
      }

    }
  }
  return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){


  return WRC_Continue;
}

/*
** Analyze the given expression looking for aggregate functions and
** for variables that need to be added to the pParse->aAgg[] array.
** Make additional entries to the pParse->aAgg[] array as necessary.
................................................................................
    int iDb = db->nDb - 1;
    assert( iDb>=2 );
    if( db->aDb[iDb].pBt ){
      sqlite3BtreeClose(db->aDb[iDb].pBt);
      db->aDb[iDb].pBt = 0;
      db->aDb[iDb].pSchema = 0;
    }
    sqlite3ResetInternalSchema(db, -1);
    db->nDb = iDb;
    if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
      db->mallocFailed = 1;
      sqlite3DbFree(db, zErrDyn);
      zErrDyn = sqlite3MPrintf(db, "out of memory");
    }else if( zErrDyn==0 ){
      zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
................................................................................
    sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
    goto detach_error;
  }

  sqlite3BtreeClose(pDb->pBt);
  pDb->pBt = 0;
  pDb->pSchema = 0;
  sqlite3ResetInternalSchema(db, -1);
  return;

detach_error:
  sqlite3_result_error(context, zErr, -1);
}

/*
................................................................................
    }
    freeIndex(db, pIndex);
  }
  db->flags |= SQLITE_InternChanges;
}

/*
** Erase all schema information from the in-memory hash tables of
** a single database.  This routine is called to reclaim memory
** before the database closes.  It is also called during a rollback
** if there were schema changes during the transaction or if a
** schema-cookie mismatch occurs.
**
** If iDb<0 then reset the internal schema tables for all database
** files.  If iDb>=0 then reset the internal schema for only the
** single file indicated.


*/
SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
  int i, j;
  assert( iDb<db->nDb );

  if( iDb>=0 ){
    /* Case 1:  Reset the single schema identified by iDb */
    Db *pDb = &db->aDb[iDb];
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    assert( pDb->pSchema!=0 );
    sqlite3SchemaClear(pDb->pSchema);

    /* If any database other than TEMP is reset, then also reset TEMP
    ** since TEMP might be holding triggers that reference tables in the
    ** other database.
    */
    if( iDb!=1 ){
      pDb = &db->aDb[1];
      assert( pDb->pSchema!=0 );
      sqlite3SchemaClear(pDb->pSchema);
    }
    return;
  }
  /* Case 2 (from here to the end): Reset all schemas for all attached
  ** databases. */
  assert( iDb<0 );
  sqlite3BtreeEnterAll(db);
  for(i=0; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    if( pDb->pSchema ){
      sqlite3SchemaClear(pDb->pSchema);
    }
  }
  db->flags &= ~SQLITE_InternChanges;
  sqlite3VtabUnlockList(db);
  sqlite3BtreeLeaveAll(db);

  /* If one or more of the auxiliary database files has been closed,
  ** then remove them from the auxiliary database list.  We take the
  ** opportunity to do this here since we have just deleted all of the
  ** schema hash tables and therefore do not have to make any changes
  ** to any of those tables.
  */
  for(i=j=2; i<db->nDb; i++){
    struct Db *pDb = &db->aDb[i];
    if( pDb->pBt==0 ){
      sqlite3DbFree(db, pDb->zName);
      pDb->zName = 0;
      continue;
    }
................................................................................
  db->nDb = j;
  if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
    memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
    sqlite3DbFree(db, db->aDb);
    db->aDb = db->aDbStatic;
  }
}














































/*
** This routine is called when a commit occurs.
*/
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
  db->flags &= ~SQLITE_InternChanges;
}
................................................................................
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
** the table data structure from the hash table.  But it does destroy
** memory structures of the indices and foreign keys associated with 
** the table.






*/
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
  Index *pIndex, *pNext;


  assert( !pTable || pTable->nRef>0 );

  /* Do not delete the table until the reference count reaches zero. */
  if( !pTable ) return;
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;







  /* Delete all indices associated with this table. */
  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
    pNext = pIndex->pNext;
    assert( pIndex->pSchema==pTable->pSchema );
    if( !db || db->pnBytesFreed==0 ){
      char *zName = pIndex->zName; 
................................................................................
#ifndef SQLITE_OMIT_CHECK
  sqlite3ExprListDelete(db, pTable->pCheck);
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3VtabClear(db, pTable);
#endif
  sqlite3DbFree(db, pTable);



}

/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
*/
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
................................................................................
    memset(&sSrc, 0, sizeof(sSrc));
    sSrc.nSrc = 1;
    sSrc.a[0].zName = p->zName;
    sSrc.a[0].pTab = p;
    sSrc.a[0].iCursor = -1;
    sNC.pParse = pParse;
    sNC.pSrcList = &sSrc;
    sNC.isCheck = 1;
    pList = p->pCheck;
    for(i=0; i<pList->nExpr; i++){
      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
        return;
      }
    }
  }
................................................................................
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;
      nExtra -= nColl;
    }else{
      zColl = pTab->aCol[j].zColl;
      if( !zColl ){
        zColl = db->pDfltColl->zName;
      }
    }
    if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
      goto exit_create_index;
    }
    pIndex->azColl[i] = zColl;
    requestedSortOrder = pListItem->sortOrder & sortOrderMask;
................................................................................
** "NULL".  Otherwise, the argument is enclosed in single quotes with
** single-quote escapes.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite3_value_type(argv[0]) ){
    case SQLITE_INTEGER:











    case SQLITE_FLOAT: {
      sqlite3_result_value(context, argv[0]);
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;
      char const *zBlob = sqlite3_value_blob(argv[0]);
      int nBlob = sqlite3_value_bytes(argv[0]);
................................................................................
    if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
      sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
        "from within a transaction");
      return SQLITE_ERROR;
    }
    sqlite3BtreeClose(db->aDb[1].pBt);
    db->aDb[1].pBt = 0;
    sqlite3ResetInternalSchema(db, -1);
  }
  return SQLITE_OK;
}
#endif /* SQLITE_PAGER_PRAGMAS */

#ifndef SQLITE_OMIT_PAGER_PRAGMAS
/*
................................................................................
        sqlite3_temp_directory = sqlite3_mprintf("%s", zRight);
      }else{
        sqlite3_temp_directory = 0;
      }
#endif /* SQLITE_OMIT_WSD */
    }
  }else













































#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
#  if defined(__APPLE__)
#    define SQLITE_ENABLE_LOCKING_STYLE 1
#  else
#    define SQLITE_ENABLE_LOCKING_STYLE 0
#  endif
................................................................................
  if( meta[BTREE_TEXT_ENCODING-1] ){  /* text encoding */
    if( iDb==0 ){
      u8 encoding;
      /* If opening the main database, set ENC(db). */
      encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
      if( encoding==0 ) encoding = SQLITE_UTF8;
      ENC(db) = encoding;
      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
    }else{
      /* If opening an attached database, the encoding much match ENC(db) */
      if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
        sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
            " text encoding as main database");
        rc = SQLITE_ERROR;
        goto initone_error_out;
................................................................................
    if( rc==SQLITE_OK ){
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM;
    sqlite3ResetInternalSchema(db, -1);
  }
  if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
    /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
    ** the schema loaded, even if errors occurred. In this situation the 
    ** current sqlite3_prepare() operation will fail, but the following one
    ** will attempt to compile the supplied statement against whatever subset
    ** of the schema was loaded before the error occurred. The primary
................................................................................
  assert( sqlite3_mutex_held(db->mutex) );
  rc = SQLITE_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
    rc = sqlite3InitOne(db, i, pzErrMsg);
    if( rc ){
      sqlite3ResetInternalSchema(db, i);
    }
  }

  /* Once all the other databases have been initialised, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
#ifndef SQLITE_OMIT_TEMPDB
  if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqlite3InitOne(db, 1, pzErrMsg);
    if( rc ){
      sqlite3ResetInternalSchema(db, 1);
    }
  }
#endif

  db->init.busy = 0;
  if( rc==SQLITE_OK && commit_internal ){
    sqlite3CommitInternalChanges(db);
................................................................................

    /* Read the schema cookie from the database. If it does not match the 
    ** value stored as part of the in-memory schema representation,
    ** set Parse.rc to SQLITE_SCHEMA. */
    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
    if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
      sqlite3ResetInternalSchema(db, iDb);
      pParse->rc = SQLITE_SCHEMA;
    }

    /* Close the transaction, if one was opened. */
    if( openedTransaction ){
      sqlite3BtreeCommit(pBt);
    }
................................................................................
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  if( rc==SQLITE_SCHEMA ){
    sqlite3_finalize(*ppStmt);
    rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
  }
  sqlite3BtreeLeaveAll(db);
  sqlite3_mutex_leave(db->mutex);

  return rc;
}

/*
** Rerun the compilation of a statement after a schema change.
**
** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
................................................................................
  }
  pTab = p->pSrc->a[0].pTab;
  pExpr = p->pEList->a[0].pExpr;
  assert( pTab && !pTab->pSelect && pExpr );

  if( IsVirtual(pTab) ) return 0;
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;

  if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
  if( pExpr->flags&EP_Distinct ) return 0;

  return pTab;
}

/*
................................................................................
    sqlite3ExprAnalyzeAggList(&sNC, pOrderBy);
    if( pHaving ){
      sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
    }
    sAggInfo.nAccumulator = sAggInfo.nColumn;
    for(i=0; i<sAggInfo.nFunc; i++){
      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );

      sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);

    }
    if( db->mallocFailed ) goto select_end;

    /* Processing for aggregates with GROUP BY is very different and
    ** much more complex than aggregates without a GROUP BY.
    */
    if( pGroupBy ){
................................................................................
    sqlite3BtreeClose(pDb->pBt);
    pDb->pBt = 0;
    pDb->pSchema = 0;
  }

  /* This both clears the schemas and reduces the size of the db->aDb[]
  ** array. */ 
  sqlite3ResetInternalSchema(db, -1);

  return rc;
}

#endif  /* SQLITE_OMIT_VACUUM && SQLITE_OMIT_ATTACH */

/************** End of vacuum.c **********************************************/
................................................................................
** Before a virtual table xCreate() or xConnect() method is invoked, the
** sqlite3.pVtabCtx member variable is set to point to an instance of
** this struct allocated on the stack. It is used by the implementation of 
** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
** are invoked only from within xCreate and xConnect methods.
*/
struct VtabCtx {
  Table *pTab;
  VTable *pVTable;
};

/*
** The actual function that does the work of creating a new module.
** This function implements the sqlite3_create_module() and
** sqlite3_create_module_v2() interfaces.
*/
................................................................................
static int createModule(
  sqlite3 *db,                    /* Database in which module is registered */
  const char *zName,              /* Name assigned to this module */
  const sqlite3_module *pModule,  /* The definition of the module */
  void *pAux,                     /* Context pointer for xCreate/xConnect */
  void (*xDestroy)(void *)        /* Module destructor function */
){

  int rc, nName;
  Module *pMod;

  sqlite3_mutex_enter(db->mutex);
  nName = sqlite3Strlen30(zName);




  pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
  if( pMod ){
    Module *pDel;
    char *zCopy = (char *)(&pMod[1]);
    memcpy(zCopy, zName, nName+1);
    pMod->zName = zCopy;
    pMod->pModule = pModule;
    pMod->pAux = pAux;
    pMod->xDestroy = xDestroy;
    pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
    if( pDel && pDel->xDestroy ){
      sqlite3ResetInternalSchema(db, -1);
      pDel->xDestroy(pDel->pAux);
    }
    sqlite3DbFree(db, pDel);
    if( pDel==pMod ){
      db->mallocFailed = 1;

    }
  }else if( xDestroy ){
    xDestroy(pAux);
  }

  rc = sqlite3ApiExit(db, SQLITE_OK);


  sqlite3_mutex_leave(db->mutex);
  return rc;
}


/*
** External API function used to create a new virtual-table module.
................................................................................
    }
    pVTable = pNext;
  }

  assert( !db || pRet );
  return pRet;
}



























/*
** Disconnect all the virtual table objects in the sqlite3.pDisconnect list.
**
** This function may only be called when the mutexes associated with all
** shared b-tree databases opened using connection db are held by the 
................................................................................
static int vtabCallConstructor(
  sqlite3 *db, 
  Table *pTab,
  Module *pMod,
  int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
  char **pzErr
){
  VtabCtx sCtx;
  VTable *pVTable;
  int rc;
  const char *const*azArg = (const char *const*)pTab->azModuleArg;
  int nArg = pTab->nModuleArg;
  char *zErr = 0;
  char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);

................................................................................
  pVTable->pMod = pMod;

  /* Invoke the virtual table constructor */
  assert( &db->pVtabCtx );
  assert( xConstruct );
  sCtx.pTab = pTab;
  sCtx.pVTable = pVTable;

  db->pVtabCtx = &sCtx;
  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
  db->pVtabCtx = 0;
  if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;

  if( SQLITE_OK!=rc ){
    if( zErr==0 ){
      *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
    }else {
      *pzErr = sqlite3MPrintf(db, "%s", zErr);
................................................................................
  **
  **   1. The index is itself UNIQUE, and
  **
  **   2. All of the columns in the index are either part of the pDistinct
  **      list, or else the WHERE clause contains a term of the form "col=X",
  **      where X is a constant value. The collation sequences of the
  **      comparison and select-list expressions must match those of the index.



  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->onError==OE_None ) continue;
    for(i=0; i<pIdx->nColumn; i++){
      int iCol = pIdx->aiColumn[i];
      if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) 
       && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i)
      ){
        break;

      }
    }
    if( i==pIdx->nColumn ){
      /* This index implies that the DISTINCT qualifier is redundant. */
      return 1;
    }
  }
................................................................................
  if( j>=nTerm ){
    /* All terms of the ORDER BY clause are covered by this index so
    ** this index can be used for sorting. */
    return 1;
  }
  if( pIdx->onError!=OE_None && i==pIdx->nColumn
      && (wsFlags & WHERE_COLUMN_NULL)==0
      && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){



    /* All terms of this index match some prefix of the ORDER BY clause
    ** and the index is UNIQUE and no terms on the tail of the ORDER BY
    ** clause reference other tables in a join.  If this is all true then
    ** the order by clause is superfluous.  Not that if the matching
    ** condition is IS NULL then the result is not necessarily unique
    ** even on a UNIQUE index, so disallow those cases. */











    return 1;
  }
  return 0;
}

/*
** Prepare a crude estimate of the logarithm of the input value.
** The results need not be exact.  This is only used for estimating
................................................................................
#define YYSTACKDEPTH 100
#endif
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
#define YYNSTATE 627
#define YYNRULE 325
#define YYFALLBACK 1
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)

/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
................................................................................
**                     yy_action.  Used to detect hash collisions.
**  yy_shift_ofst[]    For each state, the offset into yy_action for
**                     shifting terminals.
**  yy_reduce_ofst[]   For each state, the offset into yy_action for
**                     shifting non-terminals after a reduce.
**  yy_default[]       Default action for each state.
*/
#define YY_ACTTAB_COUNT (1561)
static const YYACTIONTYPE yy_action[] = {
 /*     0 */   310,  328,  573,  572,   15,  171,  185,  595,   56,   56,
 /*    10 */    56,   56,   49,   54,   54,   54,   54,   53,   53,   52,
 /*    20 */    52,   52,   51,  233,   52,   52,   52,   51,  233,  624,
 /*    30 */   588,  582,   56,   56,   56,   56,  314,   54,   54,   54,
 /*    40 */    54,   53,   53,   52,   52,   52,   51,  233,  299,   57,
 /*    50 */    58,   48,  580,  579,  581,  581,   55,   55,   56,   56,
 /*    60 */    56,   56,  569,   54,   54,   54,   54,   53,   53,   52,
 /*    70 */    52,   52,   51,  233,  310,  595,  326,  575,  663,   65,
 /*    80 */    33,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*    90 */    51,  233,   53,   53,   52,   52,   52,   51,  233,  489,
 /*   100 */   663,  440,  663,  235,  588,  582,  553,  297,  363,   59,
 /*   110 */   481,   67,  360,    1,  618,  351,  618,  620,  619,  207,
 /*   120 */     6,  441,  442,   57,   58,   48,  580,  579,  581,  581,
 /*   130 */    55,   55,   56,   56,   56,   56,  605,   54,   54,   54,
 /*   140 */    54,   53,   53,   52,   52,   52,   51,  233,  310,  223,
 /*   150 */    50,   47,  146,  598,  138,  281,  385,  276,  384,  168,
 /*   160 */   489,  552,  620,  619,  620,  619,  272,  214,  440,  411,
 /*   170 */   551,  604,   67,  165,    7,  618,  352,  353,  588,  582,
 /*   180 */   443,  569,  192,  618,  414,  617,  616,  668,  441,  336,
 /*   190 */   669,   62,  618,  599,   92,  382,  346,   57,   58,   48,
 /*   200 */   580,  579,  581,  581,   55,   55,   56,   56,   56,   56,
 /*   210 */   670,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   220 */    51,  233,  310,  465,  232,  231,  373,  132,  514,  513,
 /*   230 */   617,  616,  617,  616,  398,  437,  411,   66,  280,  388,
 /*   240 */   411,  595,  439,  220,  438,  620,  619,  337,  569,  279,
 /*   250 */   201,  414,  588,  582,  166,  414,  546,  167,   68,  234,
 /*   260 */   599,   92,  620,  619,  599,   92,   19,  570,  570,  466,
 /*   270 */   564,   57,   58,   48,  580,  579,  581,  581,   55,   55,
 /*   280 */    56,   56,   56,   56,  598,   54,   54,   54,   54,   53,
 /*   290 */    53,   52,   52,   52,   51,  233,  310,  411,  524,  232,
 /*   300 */   231,  398,  593,  547,  559,  398,  348,  202,  175,  595,
 /*   310 */   399,  315,  414,  617,  616,  387,  272,  255,  347,  254,
 /*   320 */   558,  599,   74,  620,  619,   45,  588,  582,  235,  466,
 /*   330 */   617,  616,  511,  591,  591,  591,  557,  578,  402,  545,
 /*   340 */   600,  598,  570,  570,  601,   57,   58,   48,  580,  579,
 /*   350 */   581,  581,   55,   55,   56,   56,   56,   56,  550,   54,
 /*   360 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
 /*   370 */   310,  309,  411,  145,  566,  490,  213,  255,  347,  254,
 /*   380 */   196,  195,  194,  587,  586,  531,  600,  414,  235,  174,
 /*   390 */   601,  617,  616,  411,  620,  619,  599,   91,  547,  574,
 /*   400 */   588,  582,   50,   47,  146,  584,  583,  471,  414,  249,
 /*   410 */   565,  542,  186,   39,  304,  424,  562,  599,   16,   57,
 /*   420 */    58,   48,  580,  579,  581,  581,   55,   55,   56,   56,
 /*   430 */    56,   56,  585,   54,   54,   54,   54,   53,   53,   52,
 /*   440 */    52,   52,   51,  233,  310,  559,  290,  530,  529,  345,
 /*   450 */   533,  576,  540,  246,  170,  248,  411,  396,  411,  422,
 /*   460 */   199,  558,  617,  616,  165,  563,   50,   47,  146,  181,
 /*   470 */   498,  414,  166,  414,  588,  582,  269,  557,  166,  518,
 /*   480 */   599,   92,  599,   92,  561,  595,  469,   36,  173,  409,
 /*   490 */   517,  577,  577,   57,   58,   48,  580,  579,  581,  581,
 /*   500 */    55,   55,   56,   56,   56,   56,  338,   54,   54,   54,
 /*   510 */    54,   53,   53,   52,   52,   52,   51,  233,  310,  304,
 /*   520 */   423,  394,  526,  318,  869,  235,  167,  180,  473,  547,
 /*   530 */   503,  247,  474,  381,  378,  377,  409,  351,  577,  577,
 /*   540 */   409,  560,  577,  577,  376,  383,  364,  603,  588,  582,
 /*   550 */   620,  619,  502,  595,  409,  494,  577,  577,  409,  266,
 /*   560 */   577,  577,  421,  943,  422,  943,  198,   57,   58,   48,
 /*   570 */   580,  579,  581,  581,   55,   55,   56,   56,   56,   56,
 /*   580 */   315,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   590 */    51,  233,  310,  390,  421,  942,  509,  942,  556,  145,
 /*   600 */   598,  391,  324,  262,  549,  264,  411,  425,  407,  573,
 /*   610 */   572,   12,  197,  143,  489,   50,   47,  146,  617,  616,
 /*   620 */   206,  414,  588,  582,  547,  429,   67,  212,  143,  618,
 /*   630 */   599,   73,  504,  505,  207,  434,  475,  475,  366,  425,
 /*   640 */    35,   57,   58,   48,  580,  579,  581,  581,   55,   55,
 /*   650 */    56,   56,   56,   56,  598,   54,   54,   54,   54,   53,
 /*   660 */    53,   52,   52,   52,   51,  233,  310,  260,  598,  569,
 /*   670 */   268,  615,  614,  613,  171,  411,  595,   11,  411,  350,
 /*   680 */   411,   32,  618,  953,  183,  419,    2,  627,  625,  330,
 /*   690 */   414,  352,  552,  414,  538,  414,  588,  582,  188,  599,
 /*   700 */    69,  551,  599,   94,  599,   97,  374,  544,  166,  618,
 /*   710 */   334,  359,   50,   47,  146,   57,   58,   48,  580,  579,
 /*   720 */   581,  581,   55,   55,   56,   56,   56,   56,  411,   54,
 /*   730 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
 /*   740 */   310,  411,  129,  414,  595,   22,  273,  156,  411,  566,
 /*   750 */   406,  213,  599,   95,  570,  570,  414,  327,  169,  332,
 /*   760 */   411,  618,  536,  414,  358,  599,  104,  483,  508,  356,
 /*   770 */   588,  582,  599,  103,  484,  414,  470,  357,  166,  618,
 /*   780 */   626,    2,  204,  323,  599,  105,   40,  528,   38,   57,
 /*   790 */    58,   48,  580,  579,  581,  581,   55,   55,   56,   56,
 /*   800 */    56,   56,  411,   54,   54,   54,   54,   53,   53,   52,
 /*   810 */    52,   52,   51,  233,  310,  411,  598,  414,  411,  260,
 /*   820 */   273,  273,  273,  273,  426,  305,  599,  106,  520,  519,
 /*   830 */   414,  411,  142,  414,  618,  618,  618,  618,  618,  599,
 /*   840 */   133,  339,  599,  134,  588,  582,  414,   21,   30,  316,
 /*   850 */   147,  459,  221,  170,  527,  599,   98,  222,  322,  321,
 /*   860 */   320,  141,  259,   57,   58,   48,  580,  579,  581,  581,
 /*   870 */    55,   55,   56,   56,   56,   56,  411,   54,   54,   54,
 /*   880 */    54,   53,   53,   52,   52,   52,   51,  233,  310,  411,
 /*   890 */   260,  414,  411,  458,  200,   35,  411,  358,  211,  228,
 /*   900 */   599,  102,  468,  519,  414,  618,   28,  414,  538,  501,
 /*   910 */   411,  414,  618,  599,  101,  358,  599,   93,  588,  582,
 /*   920 */   599,  100,  522,  618,  427,  414,  306,  271,  598,  380,
 /*   930 */   618,  602,  598,  452,  599,   77,  210,   57,   58,   48,
 /*   940 */   580,  579,  581,  581,   55,   55,   56,   56,   56,   56,
 /*   950 */   411,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   960 */    51,  233,  310,  411,  621,  414,  411,  127,  609,  270,
 /*   970 */   598,  365,   51,  233,  599,   96,  625,  330,  414,  618,
 /*   980 */   126,  414,  411,  618,  411,  253,  608,  599,  137,   27,
 /*   990 */   599,  136,  588,  582,  375,  260,  125,  414,  164,  414,
 /*  1000 */   371,  618,  279,  219,  542,  542,  599,  135,  599,   76,
 /*  1010 */   618,   57,   46,   48,  580,  579,  581,  581,   55,   55,
 /*  1020 */    56,   56,   56,   56,  411,   54,   54,   54,   54,   53,
 /*  1030 */    53,   52,   52,   52,   51,  233,  310,  411,  450,  414,
 /*  1040 */   411,  260,  542,  229,  285,  607,  479,  184,  599,   90,
 /*  1050 */   367,  122,  414,  476,  121,  414,  618,  170,  411,  353,
 /*  1060 */   618,  599,   89,  410,  599,   75,  588,  582,  472,  257,
 /*  1070 */   538,  120,  159,  414,  618,   14,  464,  158,  618,  157,
 /*  1080 */   461,  283,  599,   88,  449,  618,   58,   48,  580,  579,
 /*  1090 */   581,  581,   55,   55,   56,   56,   56,   56,  411,   54,
 /*  1100 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  233,
 /*  1110 */   310,  411,  260,  414,  411,  592,  260,  118,   25,  400,
 /*  1120 */    10,   24,  599,   87,  117,  216,  414,  618,  349,  414,
 /*  1130 */   618,  618,  411,  319,  618,  599,   99,  555,  599,   86,
 /*  1140 */   588,  582,    4,  260,  457,  455,  115,  414,  251,  154,
 /*  1150 */   451,  108,  618,  110,  436,  448,  599,   17,  618,  218,
 /*  1160 */   107,   48,  580,  579,  581,  581,   55,   55,   56,   56,
 /*  1170 */    56,   56,  435,   54,   54,   54,   54,   53,   53,   52,
 /*  1180 */    52,   52,   51,  233,   44,  405,  217,    3,  411,  260,
 /*  1190 */   543,  415,  619,  445,   64,  149,  539,  237,  333,  329,
 /*  1200 */   203,  187,  408,  414,  618,  618,  420,   44,  405,  411,
 /*  1210 */     3,  618,  599,   85,  415,  619,  148,  227,  622,  179,
 /*  1220 */   313,  403,  312,  612,  414,  408,  611,  124,  417,  178,
 /*  1230 */   610,  564,  243,  599,   84,  537,    8,  176,  235,  416,
 /*  1240 */   294,  418,  623,   30,  403,  597,  411,  236,  293,  123,
 /*  1250 */   618,   41,   42,  532,  564,  205,  292,  275,   43,  413,
 /*  1260 */   412,  414,  395,  593,  507,  274,   31,  397,  291,   37,
 /*  1270 */   599,   83,  618,  491,   41,   42,  267,  411,  265,  618,
 /*  1280 */   618,   43,  413,  412,  596,  263,  593,   60,  618,  598,
 /*  1290 */   261,  618,  414,  618,  591,  591,  591,  590,  589,   13,
 /*  1300 */   618,  599,   72,  554,  235,  618,   44,  405,  256,    3,
 /*  1310 */   361,  172,  340,  415,  619,  230,  411,  591,  591,  591,
 /*  1320 */   590,  589,   13,  618,  408,  618,  182,  411,  286,   34,
 /*  1330 */   405,  414,    3,  411,  463,  411,  415,  619,   29,  331,
 /*  1340 */   599,   71,  414,  403,  392,  386,  284,  408,  414,  618,
 /*  1350 */   414,  599,   82,  564,  411,  462,  354,  599,   81,  599,
 /*  1360 */    80,  541,  250,  535,  282,  521,  403,  534,  516,  414,
 /*  1370 */   618,  618,  454,   41,   42,  411,  564,  618,  599,   70,
 /*  1380 */    43,  413,  412,  444,  515,  593,  242,  618,  325,   61,
 /*  1390 */   414,  277,  239,  620,  619,  238,   41,   42,  618,  599,
 /*  1400 */    18,  618,  512,   43,  413,  412,  511,  618,  593,  430,
 /*  1410 */   618,  411,  128,  510,  308,  226,  591,  591,  591,  590,
 /*  1420 */   589,   13,  215,  289,  618,  225,  414,  302,  301,  300,
 /*  1430 */   177,  298,  411,  564,  453,  599,   79,  224,  618,  591,
 /*  1440 */   591,  591,  590,  589,   13,  389,  492,  414,  150,  144,
 /*  1450 */   241,  393,  288,  191,  190,  193,  599,   78,  165,  240,
 /*  1460 */   414,  524,  487,  307,  618,  593,  618,  618,  486,  599,
 /*  1470 */     9,  163,  152,  485,  466,  372,  480,  162,  153,  370,
 /*  1480 */   161,  151,  209,  478,  258,  368,  477,   26,  160,  467,
 /*  1490 */   140,  362,  131,  119,  116,  456,  591,  591,  591,  155,
 /*  1500 */   114,  344,  343,  113,  112,  111,  447,  109,  130,   23,
 /*  1510 */   317,  433,   20,  432,  431,  428,  606,  594,   63,  189,
 /*  1520 */   404,  571,  255,  342,  244,  295,  287,  278,  311,  508,
 /*  1530 */   496,  497,  495,  235,  493,  568,  379,  355,  460,  245,
 /*  1540 */   341,  446,  303,  567,    5,  252,  548,  208,  139,  506,
 /*  1550 */   369,  401,  500,  499,  296,  525,  335,  488,  482,  523,
 /*  1560 */   233,
};
static const YYCODETYPE yy_lookahead[] = {
 /*     0 */    19,  169,  170,  171,   22,   24,   24,   26,   77,   78,
 /*    10 */    79,   80,   81,   82,   83,   84,   85,   86,   87,   88,
 /*    20 */    89,   90,   91,   92,   88,   89,   90,   91,   92,    1,
 /*    30 */    49,   50,   77,   78,   79,   80,  155,   82,   83,   84,
 /*    40 */    85,   86,   87,   88,   89,   90,   91,   92,   15,   68,
 /*    50 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*    60 */    79,   80,  230,   82,   83,   84,   85,   86,   87,   88,
 /*    70 */    89,   90,   91,   92,   19,   94,   19,   23,    1,   25,
 /*    80 */    25,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*    90 */    91,   92,   86,   87,   88,   89,   90,   91,   92,  150,
 /*   100 */    23,  150,   25,  116,   49,   50,  177,  158,  227,   54,
 /*   110 */   161,  162,  231,   22,  165,  128,  165,   26,   27,  160,
 /*   120 */    22,  170,  171,   68,   69,   70,   71,   72,   73,   74,
 /*   130 */    75,   76,   77,   78,   79,   80,   23,   82,   83,   84,
 /*   140 */    85,   86,   87,   88,   89,   90,   91,   92,   19,   92,
 /*   150 */   221,  222,  223,  194,   97,   98,   99,  100,  101,  102,
 /*   160 */   150,   32,   26,   27,   26,   27,  109,   22,  150,  150,
 /*   170 */    41,  161,  162,   96,   76,  165,  217,  150,   49,   50,
 /*   180 */   229,  230,  172,  165,  165,   94,   95,  118,  170,  171,
 /*   190 */   118,  232,  165,  174,  175,  185,  237,   68,   69,   70,
 /*   200 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   210 */   118,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   220 */    91,   92,   19,   11,   86,   87,   19,   24,    7,    8,
 /*   230 */    94,   95,   94,   95,  215,   97,  150,   22,   98,  220,
 /*   240 */   150,   26,  104,  216,  106,   26,   27,  229,  230,  109,
 /*   250 */   160,  165,   49,   50,   25,  165,  120,   50,   22,  197,
 /*   260 */   174,  175,   26,   27,  174,  175,  204,  129,  130,   57,
 /*   270 */    66,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   280 */    77,   78,   79,   80,  194,   82,   83,   84,   85,   86,
 /*   290 */    87,   88,   89,   90,   91,   92,   19,  150,   94,   86,
 /*   300 */    87,  215,   98,   25,   12,  215,  220,  160,  118,   94,
 /*   310 */   220,  104,  165,   94,   95,   88,  109,  105,  106,  107,
 /*   320 */    28,  174,  175,   26,   27,   22,   49,   50,  116,   57,
 /*   330 */    94,   95,  103,  129,  130,  131,   44,  113,   46,  120,
 /*   340 */   113,  194,  129,  130,  117,   68,   69,   70,   71,   72,
 /*   350 */    73,   74,   75,   76,   77,   78,   79,   80,  177,   82,
 /*   360 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   370 */    19,  163,  150,   95,  166,  167,  168,  105,  106,  107,
 /*   380 */   105,  106,  107,   49,   50,   88,  113,  165,  116,  118,
 /*   390 */   117,   94,   95,  150,   26,   27,  174,  175,  120,   23,
 /*   400 */    49,   50,  221,  222,  223,   71,   72,   21,  165,   16,
 /*   410 */    23,  166,   22,  136,   22,   23,   11,  174,  175,   68,
 /*   420 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   430 */    79,   80,   98,   82,   83,   84,   85,   86,   87,   88,
 /*   440 */    89,   90,   91,   92,   19,   12,  224,   23,   23,   63,
 /*   450 */   205,   23,   23,   60,   25,   62,  150,  214,  150,   67,
 /*   460 */    22,   28,   94,   95,   96,   23,  221,  222,  223,   23,
 /*   470 */    23,  165,   25,  165,   49,   50,   23,   44,   25,   46,
 /*   480 */   174,  175,  174,  175,   23,   26,  100,  136,   25,  112,
 /*   490 */    57,  114,  115,   68,   69,   70,   71,   72,   73,   74,
 /*   500 */    75,   76,   77,   78,   79,   80,   97,   82,   83,   84,
 /*   510 */    85,   86,   87,   88,   89,   90,   91,   92,   19,   22,
 /*   520 */    23,  215,   23,  215,  138,  116,   50,   23,   30,   25,
 /*   530 */    36,  138,   34,   99,  100,  101,  112,  128,  114,  115,
 /*   540 */   112,   23,  114,  115,  110,   51,   48,  173,   49,   50,
 /*   550 */    26,   27,   58,   94,  112,  181,  114,  115,  112,   16,
 /*   560 */   114,  115,   22,   23,   67,   25,  160,   68,   69,   70,
 /*   570 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   580 */   104,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   590 */    91,   92,   19,   19,   22,   23,   23,   25,   23,   95,
 /*   600 */   194,   27,  108,   60,   25,   62,  150,   67,  169,  170,
 /*   610 */   171,   35,  206,  207,  150,  221,  222,  223,   94,   95,
 /*   620 */   160,  165,   49,   50,  120,  161,  162,  206,  207,  165,
 /*   630 */   174,  175,   97,   98,  160,  241,  105,  106,  107,   67,
 /*   640 */    25,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   650 */    77,   78,   79,   80,  194,   82,   83,   84,   85,   86,
 /*   660 */    87,   88,   89,   90,   91,   92,   19,  150,  194,  230,
 /*   670 */    23,    7,    8,    9,   24,  150,   26,   35,  150,  219,
 /*   680 */   150,   25,  165,  142,  143,  144,  145,    0,    1,    2,
 /*   690 */   165,  217,   32,  165,  150,  165,   49,   50,  119,  174,
 /*   700 */   175,   41,  174,  175,  174,  175,   23,  120,   25,  165,
 /*   710 */   193,  237,  221,  222,  223,   68,   69,   70,   71,   72,
 /*   720 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
 /*   730 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*   740 */    19,  150,   22,  165,   94,   24,  150,   25,  150,  166,
 /*   750 */   167,  168,  174,  175,  129,  130,  165,  213,   35,  242,
 /*   760 */   150,  165,   27,  165,  150,  174,  175,  181,  182,   19,
 /*   770 */    49,   50,  174,  175,  188,  165,   23,   27,   25,  165,
 /*   780 */   144,  145,  160,  187,  174,  175,  135,   23,  137,   68,
 /*   790 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   800 */    79,   80,  150,   82,   83,   84,   85,   86,   87,   88,
 /*   810 */    89,   90,   91,   92,   19,  150,  194,  165,  150,  150,
 /*   820 */   150,  150,  150,  150,  247,  248,  174,  175,  190,  191,
 /*   830 */   165,  150,  118,  165,  165,  165,  165,  165,  165,  174,
 /*   840 */   175,  219,  174,  175,   49,   50,  165,   52,  126,  245,
 /*   850 */   246,   23,  238,   25,   23,  174,  175,  187,  187,  187,
 /*   860 */   187,   39,  193,   68,   69,   70,   71,   72,   73,   74,
 /*   870 */    75,   76,   77,   78,   79,   80,  150,   82,   83,   84,
 /*   880 */    85,   86,   87,   88,   89,   90,   91,   92,   19,  150,
 /*   890 */   150,  165,  150,   23,  160,   25,  150,  150,  160,   52,
 /*   900 */   174,  175,  190,  191,  165,  165,   22,  165,  150,   29,
 /*   910 */   150,  165,  165,  174,  175,  150,  174,  175,   49,   50,
 /*   920 */   174,  175,  165,  165,   23,  165,   25,   25,  194,   52,
 /*   930 */   165,  174,  194,  193,  174,  175,  160,   68,   69,   70,
 /*   940 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
 /*   950 */   150,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   960 */    91,   92,   19,  150,  150,  165,  150,   22,  150,   23,
 /*   970 */   194,  213,   91,   92,  174,  175,    1,    2,  165,  165,
 /*   980 */    22,  165,  150,  165,  150,  238,  150,  174,  175,   22,
 /*   990 */   174,  175,   49,   50,   52,  150,   22,  165,  102,  165,
 /*  1000 */    19,  165,  109,  238,  166,  166,  174,  175,  174,  175,
 /*  1010 */   165,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*  1020 */    77,   78,   79,   80,  150,   82,   83,   84,   85,   86,
 /*  1030 */    87,   88,   89,   90,   91,   92,   19,  150,  193,  165,
 /*  1040 */   150,  150,  166,  205,  205,  150,   20,   24,  174,  175,
 /*  1050 */    43,  104,  165,   59,   53,  165,  165,   25,  150,  150,
 /*  1060 */   165,  174,  175,  150,  174,  175,   49,   50,   53,  138,
 /*  1070 */   150,   22,  104,  165,  165,    5,    1,  118,  165,   35,
 /*  1080 */    27,  205,  174,  175,  193,  165,   69,   70,   71,   72,
 /*  1090 */    73,   74,   75,   76,   77,   78,   79,   80,  150,   82,
 /*  1100 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   92,
 /*  1110 */    19,  150,  150,  165,  150,  150,  150,  108,   76,  150,
 /*  1120 */    22,   76,  174,  175,  127,  216,  165,  165,   25,  165,
 /*  1130 */   165,  165,  150,  213,  165,  174,  175,  150,  174,  175,
 /*  1140 */    49,   50,   22,  150,   23,    1,  119,  165,   16,  121,
 /*  1150 */    20,  108,  165,  119,   23,  193,  174,  175,  165,  193,
 /*  1160 */   127,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*  1170 */    79,   80,   23,   82,   83,   84,   85,   86,   87,   88,
 /*  1180 */    89,   90,   91,   92,   19,   20,  193,   22,  150,  150,
 /*  1190 */   150,   26,   27,  128,   16,   15,  150,  140,   65,    3,
 /*  1200 */   164,   22,   37,  165,  165,  165,    4,   19,   20,  150,
 /*  1210 */    22,  165,  174,  175,   26,   27,  246,  180,  149,    6,
 /*  1220 */   249,   56,  249,  149,  165,   37,  149,  180,  149,  151,
 /*  1230 */    13,   66,  193,  174,  175,  150,   25,  151,  116,  159,
 /*  1240 */   199,  146,  147,  126,   56,  194,  150,  152,  200,  154,
 /*  1250 */   165,   86,   87,   88,   66,  160,  201,  150,   93,   94,
 /*  1260 */    95,  165,  123,   98,  150,  150,  124,  122,  202,  135,
 /*  1270 */   174,  175,  165,  150,   86,   87,  150,  150,  150,  165,
 /*  1280 */   165,   93,   94,   95,  203,  150,   98,  125,  165,  194,
 /*  1290 */   150,  165,  165,  165,  129,  130,  131,  132,  133,  134,
 /*  1300 */   165,  174,  175,  157,  116,  165,   19,   20,  150,   22,
 /*  1310 */   150,  118,  217,   26,   27,  225,  150,  129,  130,  131,
 /*  1320 */   132,  133,  134,  165,   37,  165,  157,  150,  210,   19,
 /*  1330 */    20,  165,   22,  150,  150,  150,   26,   27,  104,  244,
 /*  1340 */   174,  175,  165,   56,  121,  104,  210,   37,  165,  165,
 /*  1350 */   165,  174,  175,   66,  150,  150,  150,  174,  175,  174,
 /*  1360 */   175,  211,  150,  211,  210,  176,   56,  211,  176,  165,
 /*  1370 */   165,  165,  150,   86,   87,  150,   66,  165,  174,  175,
 /*  1380 */    93,   94,   95,  150,  184,   98,  150,  165,   47,   22,
 /*  1390 */   165,  176,  150,   26,   27,  150,   86,   87,  165,  174,
 /*  1400 */   175,  165,  178,   93,   94,   95,  103,  165,   98,  150,
 /*  1410 */   165,  150,   22,  176,  179,  228,  129,  130,  131,  132,
 /*  1420 */   133,  134,    5,  150,  165,   92,  165,   10,   11,   12,
 /*  1430 */    13,   14,  150,   66,   17,  174,  175,  228,  165,  129,
 /*  1440 */   130,  131,  132,  133,  134,  150,  184,  165,   31,  150,
 /*  1450 */    33,  150,  150,   86,   87,  172,  174,  175,   96,   42,
 /*  1460 */   165,   94,  176,  179,  165,   98,  165,  165,  176,  174,
 /*  1470 */   175,  156,   55,  176,   57,   18,  157,  156,   61,  157,
 /*  1480 */   156,   64,  157,  157,  235,   45,  236,  135,  156,  189,
 /*  1490 */    68,  157,  218,  189,   22,  199,  129,  130,  131,  156,
 /*  1500 */   192,  157,   18,  192,  192,  192,  199,  189,  218,  240,
 /*  1510 */   157,   40,  240,  157,  157,   38,  153,  166,  243,  196,
 /*  1520 */   226,  230,  105,  106,  107,  198,  209,  177,  111,  182,
 /*  1530 */   166,  177,  177,  116,  166,  230,  178,  239,  199,  209,
 /*  1540 */   209,  199,  148,  166,  196,  239,  208,  233,  172,  183,
 /*  1550 */   234,  191,  183,  183,  195,  174,  139,  186,  186,  174,
 /*  1560 */    92,
};
#define YY_SHIFT_USE_DFLT (-70)
#define YY_SHIFT_COUNT (418)
#define YY_SHIFT_MIN   (-69)
#define YY_SHIFT_MAX   (1484)
static const short yy_shift_ofst[] = {
 /*     0 */   975, 1188, 1417, 1188, 1287, 1287,  138,  138,  368,  -19,
 /*    10 */  1287, 1287, 1287, 1287,  272,  524,  129,  129,  795, 1165,
 /*    20 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    30 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    40 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
 /*    50 */  1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
 /*    60 */  1287, 1287,  212,  524,  524,  213,  213,  459, 1122,   55,
 /*    70 */   721,  647,  573,  499,  425,  351,  277,  203,  869,  869,
 /*    80 */   869,  869,  869,  869,  869,  869,  869,  869,  869,  869,
 /*    90 */   869,  869,  869,  943,  869, 1017, 1091, 1091,  -69,  -45,
 /*   100 */   -45,  -45,  -45,  -45,   -1,    6,  -64,  524,  524,  524,
 /*   110 */   524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
 /*   120 */   524,  524,  524,  386,  207,  524,  524,  524,  524,  524,
 /*   130 */   409,  -13,  459,  881, 1468,  -70,  -70,  -70, 1367,   57,
 /*   140 */   433,  433,  297,  236,  219,  136,   91,  572,  540,  524,
 /*   150 */   524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
 /*   160 */   524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
 /*   170 */   524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
 /*   180 */   650,  650,  650,  687, 1122, 1122, 1122,  -70,  -70,  -70,
 /*   190 */   204,  204,  434,  434,  494,  494,  494,  504,  446,  292,
 /*   200 */   442,  428,  424,   77,  377,  377,  377,  377,  531,  498,
 /*   210 */   377,  377,  278,  215,  227,  664,  722,  574,  574,  750,
 /*   220 */   722,  750,  229,  459,  660,  459,  660,  476,  660,  574,
 /*   230 */   651,  625,  625,  459,  579,  273,  -18, 1477, 1193, 1193,
 /*   240 */  1471, 1471, 1193, 1472, 1422, 1117, 1484, 1484, 1484, 1484,
 /*   250 */  1193, 1457, 1117, 1472, 1422, 1422, 1193, 1457, 1352, 1440,
 /*   260 */  1193, 1193, 1457, 1193, 1457, 1193, 1457, 1390, 1241, 1241,
 /*   270 */  1241, 1362, 1341, 1333, 1333, 1390, 1241, 1303, 1241, 1341,
 /*   280 */  1241, 1241, 1223, 1234, 1223, 1234, 1223, 1234, 1193, 1193,
 /*   290 */  1134, 1162, 1145, 1142, 1139, 1117, 1122, 1211, 1217, 1217,
 /*   300 */  1213, 1213, 1213, 1213,  -70,  -70,  -70,  -70,  -70,  -70,
 /*   310 */   334,  393,  497,  392,  543,  275,  901,   98,  870,  828,
 /*   320 */   753,  683,  453,  447,  535,  221,  140,  429,   54, 1202,
 /*   330 */  1196, 1179, 1057, 1180, 1133, 1178, 1149, 1131, 1065, 1103,
 /*   340 */  1033, 1043, 1034, 1130, 1028, 1132, 1144, 1027, 1121, 1120,
 /*   350 */  1103, 1098,  997, 1045, 1042, 1009, 1053, 1044,  959, 1075,
 /*   360 */  1070, 1049,  968,  931, 1015, 1032, 1001,  994, 1007,  947,
 /*   370 */  1023, 1026,  981,  893,  896,  974,  942,  967,  958,  946,
 /*   380 */   945,  877,  902,  880,  884,  847,  822,  831,  764,  714,
 /*   390 */   735,  723,  720,  587,  615,  642,  656,  576,  615,  575,
 /*   400 */   518,  463,  461,  438,  405,  390,  387,  376,  303,  224,
 /*   410 */   271,  190,   92,   72,   69,  145,  113,   33,   28,
};
#define YY_REDUCE_USE_DFLT (-169)
#define YY_REDUCE_COUNT (309)
#define YY_REDUCE_MIN   (-168)
#define YY_REDUCE_MAX   (1394)
static const short yy_reduce_ofst[] = {
 /*     0 */   541,   90, 1095,  147,   86,   19,   18,  -49,   10,  245,
 /*    10 */   308,  306,  243,  222,  -41,  -51,  181,  -71,  394, 1295,
 /*    20 */  1282, 1261, 1225, 1204, 1185, 1183, 1177, 1166, 1127, 1096,
 /*    30 */  1059, 1038,  982,  964,  961,  948,  908,  890,  887,  874,
 /*    40 */   834,  832,  816,  813,  800,  760,  746,  742,  739,  726,
 /*    50 */   681,  668,  665,  652,  610,  598,  591,  578,  530,  528,
 /*    60 */   525,  456,  474,  464,  517,  439, -168,  208,  406,  491,
 /*    70 */   491,  491,  491,  491,  491,  491,  491,  491,  491,  491,
 /*    80 */   491,  491,  491,  491,  491,  491,  491,  491,  491,  491,
 /*    90 */   491,  491,  491,  491,  491,  491,  491,  491,  491,  491,
 /*   100 */   491,  491,  491,  491,  491,  491,  491, 1039,  909,  993,
 /*   110 */   966,  962,  891,  845,  740,  765,  920,  747,   27,  614,
 /*   120 */   673,  758,  669, -119,  586,  672,  671,  670,  596,  544,
 /*   130 */   622,  460,  583,  491,  491,  491,  491,  491,  757,  374,
 /*   140 */   712,  638,  913, 1302, 1301, 1299, 1273,  577,  577, 1259,
 /*   150 */  1245, 1242, 1236, 1233, 1222, 1212, 1206, 1205, 1184, 1160,
 /*   160 */  1158, 1140, 1135, 1128, 1126, 1123, 1115, 1114, 1107, 1085,
 /*   170 */  1046, 1040,  987,  969,  965,  913,  895,  836,  818,  814,
 /*   180 */   876,  839,  838,  636,  776,  738,  734,  604,  421,   62,
 /*   190 */  1385, 1381, 1372, 1371, 1370, 1369, 1366, 1338, 1359, 1360,
 /*   200 */  1359, 1359, 1359, 1376, 1359, 1359, 1359, 1359, 1316, 1314,
 /*   210 */  1359, 1359, 1338, 1377, 1348, 1394, 1342, 1331, 1330, 1306,
 /*   220 */  1339, 1298, 1358, 1368, 1355, 1364, 1354, 1347, 1350, 1317,
 /*   230 */  1294, 1305, 1291, 1351, 1327, 1323, 1363, 1275, 1357, 1356,
 /*   240 */  1272, 1269, 1353, 1290, 1318, 1307, 1313, 1312, 1311, 1308,
 /*   250 */  1344, 1343, 1296, 1274, 1304, 1300, 1334, 1332, 1250, 1249,
 /*   260 */  1326, 1325, 1324, 1322, 1321, 1319, 1315, 1284, 1297, 1292,
 /*   270 */  1286, 1283, 1262, 1209, 1187, 1235, 1237, 1224, 1215, 1200,
 /*   280 */  1192, 1189, 1156, 1154, 1152, 1136, 1150, 1118, 1169, 1146,
 /*   290 */  1090, 1081, 1066, 1055, 1048, 1041, 1051, 1080, 1086, 1078,
 /*   300 */  1079, 1077, 1074, 1069,  973,  971,  970, 1047, 1037, 1036,
};
static const YYACTIONTYPE yy_default[] = {
 /*     0 */   632,  864,  952,  952,  864,  864,  952,  952,  683,  754,
 /*    10 */   952,  952,  952,  862,  952,  952,  782,  782,  926,  952,
 /*    20 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*    30 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*    40 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*    50 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*    60 */   952,  952,  952,  952,  952,  952,  952,  671,  758,  788,
 /*    70 */   952,  952,  952,  952,  952,  952,  952,  952,  925,  927,
 /*    80 */   796,  795,  905,  769,  793,  786,  790,  865,  858,  859,
 /*    90 */   857,  861,  866,  952,  789,  825,  842,  824,  836,  841,
 /*   100 */   848,  840,  837,  827,  826,  828,  829,  952,  952,  952,
 /*   110 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   120 */   952,  952,  952,  658,  723,  952,  952,  952,  952,  952,
 /*   130 */   952,  952,  952,  830,  831,  845,  844,  843,  952,  952,
 /*   140 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   150 */   932,  930,  952,  877,  952,  952,  952,  952,  952,  952,
 /*   160 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   170 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  638,
 /*   180 */   754,  754,  754,  632,  952,  952,  952,  944,  758,  748,
 /*   190 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   200 */   952,  952,  952,  683,  798,  737,  915,  917,  952,  898,
 /*   210 */   735,  660,  756,  673,  746,  640,  792,  771,  771,  910,
 /*   220 */   792,  910,  697,  952,  782,  952,  782,  694,  782,  771,
 /*   230 */   860,  952,  952,  952,  755,  746,  952,  937,  762,  762,
 /*   240 */   929,  929,  762,  804,  727,  792,  734,  734,  734,  734,
 /*   250 */   762,  655,  792,  804,  727,  727,  762,  655,  904,  902,
 /*   260 */   762,  762,  655,  762,  655,  762,  655,  870,  725,  725,
 /*   270 */   725,  683,  712,  874,  874,  870,  725,  697,  725,  712,
 /*   280 */   725,  725,  775,  770,  775,  770,  775,  770,  762,  762,
 /*   290 */   952,  787,  776,  785,  783,  792,  952,  715,  648,  648,
 /*   300 */   637,  637,  637,  637,  949,  949,  944,  699,  699,  681,
 /*   310 */   952,  952,  952,  952,  952,  952,  952,  879,  952,  952,
 /*   320 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   330 */   633,  939,  952,  952,  936,  952,  952,  952,  952,  797,
 /*   340 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   350 */   914,  952,  952,  952,  952,  952,  952,  952,  908,  952,
 /*   360 */   952,  952,  952,  952,  952,  901,  900,  952,  952,  952,
 /*   370 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*   380 */   952,  952,  716,  952,  952,  952,  952,  952,  952,  952,
 /*   390 */   952,  952,  952,  952,  784,  952,  777,  952,  863,  952,
 /*   400 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  740,
 /*   410 */   813,  952,  812,  816,  811,  665,  952,  646,  952,  629,
 /*   420 */   634,  948,  951,  950,  947,  946,  945,  940,  938,  935,
 /*   430 */   934,  933,  931,  928,  924,  883,  881,  888,  887,  886,
 /*   440 */   885,  884,  882,  880,  878,  799,  794,  791,  923,  876,
 /*   450 */   736,  733,  732,  654,  941,  907,  916,  803,  802,  805,
 /*   460 */   913,  912,  911,  909,  906,  893,  801,  800,  728,  868,
 /*   470 */   867,  657,  897,  896,  895,  899,  903,  894,  764,  656,
 /*   480 */   653,  662,  718,  724,  722,  721,  720,  719,  717,  664,
 /*   490 */   672,  682,  711,  696,  695,  873,  875,  872,  871,  704,
 /*   500 */   703,  709,  708,  707,  706,  705,  702,  701,  700,  693,
 /*   510 */   692,  698,  691,  714,  713,  710,  690,  731,  730,  729,
 /*   520 */   726,  689,  688,  687,  816,  686,  685,  822,  821,  809,
 /*   530 */   852,  751,  750,  749,  761,  760,  773,  772,  807,  806,
 /*   540 */   774,  759,  753,  752,  768,  767,  766,  765,  757,  747,
 /*   550 */   779,  781,  780,  778,  854,  763,  851,  922,  921,  920,
 /*   560 */   919,  918,  856,  855,  823,  820,  676,  677,  891,  890,
 /*   570 */   892,  889,  679,  678,  675,  674,  853,  742,  741,  849,
 /*   580 */   846,  838,  834,  850,  847,  839,  835,  833,  832,  818,
 /*   590 */   817,  815,  814,  810,  819,  667,  743,  739,  738,  808,
 /*   600 */   745,  744,  684,  680,  661,  659,  652,  650,  649,  651,
 /*   610 */   647,  645,  644,  643,  642,  641,  670,  669,  668,  666,
 /*   620 */   665,  639,  636,  635,  631,  630,  628,
};

/* The next table maps tokens into fallback tokens.  If a construct
** like the following:
** 
................................................................................
  "ecmd",          "explain",       "cmdx",          "cmd",         
  "transtype",     "trans_opt",     "nm",            "savepoint_opt",
  "create_table",  "create_table_args",  "createkw",      "temp",        
  "ifnotexists",   "dbnm",          "columnlist",    "conslist_opt",
  "select",        "column",        "columnid",      "type",        
  "carglist",      "id",            "ids",           "typetoken",   
  "typename",      "signed",        "plus_num",      "minus_num",   
  "cname",         "ccons",         "term",          "expr",        
  "onconf",        "sortorder",     "autoinc",       "idxlist_opt", 
  "refargs",       "defer_subclause",  "refarg",        "refact",      
  "init_deferred_pred_opt",  "conslist",      "tcons",         "idxlist",     
  "defer_subclause_opt",  "orconf",        "resolvetype",   "raisetype",   
  "ifexists",      "fullname",      "oneselect",     "multiselect_op",
  "distinct",      "selcollist",    "from",          "where_opt",   
  "groupby_opt",   "having_opt",    "orderby_opt",   "limit_opt",   
  "sclp",          "as",            "seltablist",    "stl_prefix",  
  "joinop",        "indexed_opt",   "on_opt",        "using_opt",   
  "joinop2",       "inscollist",    "sortlist",      "nexprlist",   
................................................................................
 /*  46 */ "typetoken ::= typename",
 /*  47 */ "typetoken ::= typename LP signed RP",
 /*  48 */ "typetoken ::= typename LP signed COMMA signed RP",
 /*  49 */ "typename ::= ids",
 /*  50 */ "typename ::= typename ids",
 /*  51 */ "signed ::= plus_num",
 /*  52 */ "signed ::= minus_num",
 /*  53 */ "carglist ::= carglist cname ccons",
 /*  54 */ "carglist ::=",
 /*  55 */ "cname ::= CONSTRAINT nm",
 /*  56 */ "cname ::=",
 /*  57 */ "ccons ::= DEFAULT term",
 /*  58 */ "ccons ::= DEFAULT LP expr RP",
 /*  59 */ "ccons ::= DEFAULT PLUS term",
 /*  60 */ "ccons ::= DEFAULT MINUS term",
 /*  61 */ "ccons ::= DEFAULT id",
 /*  62 */ "ccons ::= NULL onconf",
 /*  63 */ "ccons ::= NOT NULL onconf",
 /*  64 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
 /*  65 */ "ccons ::= UNIQUE onconf",
 /*  66 */ "ccons ::= CHECK LP expr RP",
 /*  67 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
 /*  68 */ "ccons ::= defer_subclause",
 /*  69 */ "ccons ::= COLLATE ids",
 /*  70 */ "autoinc ::=",
 /*  71 */ "autoinc ::= AUTOINCR",
 /*  72 */ "refargs ::=",
 /*  73 */ "refargs ::= refargs refarg",
 /*  74 */ "refarg ::= MATCH nm",
 /*  75 */ "refarg ::= ON INSERT refact",
 /*  76 */ "refarg ::= ON DELETE refact",
 /*  77 */ "refarg ::= ON UPDATE refact",
 /*  78 */ "refact ::= SET NULL",
 /*  79 */ "refact ::= SET DEFAULT",
 /*  80 */ "refact ::= CASCADE",
 /*  81 */ "refact ::= RESTRICT",
 /*  82 */ "refact ::= NO ACTION",
 /*  83 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
 /*  84 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
 /*  85 */ "init_deferred_pred_opt ::=",
 /*  86 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
 /*  87 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
 /*  88 */ "conslist_opt ::=",
 /*  89 */ "conslist_opt ::= COMMA conslist",

 /*  90 */ "conslist ::= conslist COMMA cname tcons",
 /*  91 */ "conslist ::= cname tcons",


 /*  92 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
 /*  93 */ "tcons ::= UNIQUE LP idxlist RP onconf",
 /*  94 */ "tcons ::= CHECK LP expr RP onconf",
 /*  95 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
 /*  96 */ "defer_subclause_opt ::=",
 /*  97 */ "defer_subclause_opt ::= defer_subclause",
 /*  98 */ "onconf ::=",
 /*  99 */ "onconf ::= ON CONFLICT resolvetype",
 /* 100 */ "orconf ::=",
 /* 101 */ "orconf ::= OR resolvetype",
 /* 102 */ "resolvetype ::= raisetype",
 /* 103 */ "resolvetype ::= IGNORE",
 /* 104 */ "resolvetype ::= REPLACE",
 /* 105 */ "cmd ::= DROP TABLE ifexists fullname",
 /* 106 */ "ifexists ::= IF EXISTS",
 /* 107 */ "ifexists ::=",
 /* 108 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
 /* 109 */ "cmd ::= DROP VIEW ifexists fullname",
 /* 110 */ "cmd ::= select",
 /* 111 */ "select ::= oneselect",
 /* 112 */ "select ::= select multiselect_op oneselect",
 /* 113 */ "multiselect_op ::= UNION",
 /* 114 */ "multiselect_op ::= UNION ALL",
 /* 115 */ "multiselect_op ::= EXCEPT|INTERSECT",
 /* 116 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
 /* 117 */ "distinct ::= DISTINCT",
 /* 118 */ "distinct ::= ALL",
 /* 119 */ "distinct ::=",
 /* 120 */ "sclp ::= selcollist COMMA",
 /* 121 */ "sclp ::=",
 /* 122 */ "selcollist ::= sclp expr as",
 /* 123 */ "selcollist ::= sclp STAR",
 /* 124 */ "selcollist ::= sclp nm DOT STAR",
 /* 125 */ "as ::= AS nm",
 /* 126 */ "as ::= ids",
 /* 127 */ "as ::=",
 /* 128 */ "from ::=",
 /* 129 */ "from ::= FROM seltablist",
 /* 130 */ "stl_prefix ::= seltablist joinop",
 /* 131 */ "stl_prefix ::=",
 /* 132 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
 /* 133 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
 /* 134 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
 /* 135 */ "dbnm ::=",
 /* 136 */ "dbnm ::= DOT nm",
 /* 137 */ "fullname ::= nm dbnm",
 /* 138 */ "joinop ::= COMMA|JOIN",
 /* 139 */ "joinop ::= JOIN_KW JOIN",
 /* 140 */ "joinop ::= JOIN_KW nm JOIN",
 /* 141 */ "joinop ::= JOIN_KW nm nm JOIN",
 /* 142 */ "on_opt ::= ON expr",
 /* 143 */ "on_opt ::=",
 /* 144 */ "indexed_opt ::=",
 /* 145 */ "indexed_opt ::= INDEXED BY nm",
 /* 146 */ "indexed_opt ::= NOT INDEXED",
 /* 147 */ "using_opt ::= USING LP inscollist RP",
 /* 148 */ "using_opt ::=",
 /* 149 */ "orderby_opt ::=",
 /* 150 */ "orderby_opt ::= ORDER BY sortlist",
 /* 151 */ "sortlist ::= sortlist COMMA expr sortorder",
 /* 152 */ "sortlist ::= expr sortorder",
 /* 153 */ "sortorder ::= ASC",
 /* 154 */ "sortorder ::= DESC",
 /* 155 */ "sortorder ::=",
 /* 156 */ "groupby_opt ::=",
 /* 157 */ "groupby_opt ::= GROUP BY nexprlist",
 /* 158 */ "having_opt ::=",
 /* 159 */ "having_opt ::= HAVING expr",
 /* 160 */ "limit_opt ::=",
 /* 161 */ "limit_opt ::= LIMIT expr",
 /* 162 */ "limit_opt ::= LIMIT expr OFFSET expr",
 /* 163 */ "limit_opt ::= LIMIT expr COMMA expr",
 /* 164 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
 /* 165 */ "where_opt ::=",
 /* 166 */ "where_opt ::= WHERE expr",
 /* 167 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
 /* 168 */ "setlist ::= setlist COMMA nm EQ expr",
 /* 169 */ "setlist ::= nm EQ expr",
 /* 170 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
 /* 171 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
 /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
 /* 173 */ "insert_cmd ::= INSERT orconf",
 /* 174 */ "insert_cmd ::= REPLACE",
 /* 175 */ "valuelist ::= VALUES LP nexprlist RP",
 /* 176 */ "valuelist ::= valuelist COMMA LP exprlist RP",
 /* 177 */ "inscollist_opt ::=",
 /* 178 */ "inscollist_opt ::= LP inscollist RP",
 /* 179 */ "inscollist ::= inscollist COMMA nm",
 /* 180 */ "inscollist ::= nm",
 /* 181 */ "expr ::= term",
 /* 182 */ "expr ::= LP expr RP",
 /* 183 */ "term ::= NULL",
 /* 184 */ "expr ::= id",
 /* 185 */ "expr ::= JOIN_KW",
 /* 186 */ "expr ::= nm DOT nm",
 /* 187 */ "expr ::= nm DOT nm DOT nm",
 /* 188 */ "term ::= INTEGER|FLOAT|BLOB",
 /* 189 */ "term ::= STRING",
 /* 190 */ "expr ::= REGISTER",
 /* 191 */ "expr ::= VARIABLE",
 /* 192 */ "expr ::= expr COLLATE ids",
 /* 193 */ "expr ::= CAST LP expr AS typetoken RP",
 /* 194 */ "expr ::= ID LP distinct exprlist RP",
 /* 195 */ "expr ::= ID LP STAR RP",
 /* 196 */ "term ::= CTIME_KW",
 /* 197 */ "expr ::= expr AND expr",
 /* 198 */ "expr ::= expr OR expr",
 /* 199 */ "expr ::= expr LT|GT|GE|LE expr",
 /* 200 */ "expr ::= expr EQ|NE expr",
 /* 201 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
 /* 202 */ "expr ::= expr PLUS|MINUS expr",
 /* 203 */ "expr ::= expr STAR|SLASH|REM expr",
 /* 204 */ "expr ::= expr CONCAT expr",
 /* 205 */ "likeop ::= LIKE_KW",
 /* 206 */ "likeop ::= NOT LIKE_KW",
 /* 207 */ "likeop ::= MATCH",
 /* 208 */ "likeop ::= NOT MATCH",
 /* 209 */ "expr ::= expr likeop expr",
 /* 210 */ "expr ::= expr likeop expr ESCAPE expr",
 /* 211 */ "expr ::= expr ISNULL|NOTNULL",
 /* 212 */ "expr ::= expr NOT NULL",
 /* 213 */ "expr ::= expr IS expr",
 /* 214 */ "expr ::= expr IS NOT expr",
 /* 215 */ "expr ::= NOT expr",
 /* 216 */ "expr ::= BITNOT expr",
 /* 217 */ "expr ::= MINUS expr",
 /* 218 */ "expr ::= PLUS expr",
 /* 219 */ "between_op ::= BETWEEN",
 /* 220 */ "between_op ::= NOT BETWEEN",
 /* 221 */ "expr ::= expr between_op expr AND expr",
 /* 222 */ "in_op ::= IN",
 /* 223 */ "in_op ::= NOT IN",
 /* 224 */ "expr ::= expr in_op LP exprlist RP",
 /* 225 */ "expr ::= LP select RP",
 /* 226 */ "expr ::= expr in_op LP select RP",
 /* 227 */ "expr ::= expr in_op nm dbnm",
 /* 228 */ "expr ::= EXISTS LP select RP",
 /* 229 */ "expr ::= CASE case_operand case_exprlist case_else END",
 /* 230 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
 /* 231 */ "case_exprlist ::= WHEN expr THEN expr",
 /* 232 */ "case_else ::= ELSE expr",
 /* 233 */ "case_else ::=",
 /* 234 */ "case_operand ::= expr",
 /* 235 */ "case_operand ::=",
 /* 236 */ "exprlist ::= nexprlist",
 /* 237 */ "exprlist ::=",
 /* 238 */ "nexprlist ::= nexprlist COMMA expr",
 /* 239 */ "nexprlist ::= expr",
 /* 240 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
 /* 241 */ "uniqueflag ::= UNIQUE",
 /* 242 */ "uniqueflag ::=",
 /* 243 */ "idxlist_opt ::=",
 /* 244 */ "idxlist_opt ::= LP idxlist RP",
 /* 245 */ "idxlist ::= idxlist COMMA nm collate sortorder",
 /* 246 */ "idxlist ::= nm collate sortorder",
 /* 247 */ "collate ::=",
 /* 248 */ "collate ::= COLLATE ids",
 /* 249 */ "cmd ::= DROP INDEX ifexists fullname",
 /* 250 */ "cmd ::= VACUUM",
 /* 251 */ "cmd ::= VACUUM nm",
 /* 252 */ "cmd ::= PRAGMA nm dbnm",
 /* 253 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
 /* 254 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
 /* 255 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
 /* 256 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
 /* 257 */ "nmnum ::= plus_num",
 /* 258 */ "nmnum ::= nm",
 /* 259 */ "nmnum ::= ON",
 /* 260 */ "nmnum ::= DELETE",
 /* 261 */ "nmnum ::= DEFAULT",
 /* 262 */ "plus_num ::= PLUS number",
 /* 263 */ "plus_num ::= number",
 /* 264 */ "minus_num ::= MINUS number",
 /* 265 */ "number ::= INTEGER|FLOAT",
 /* 266 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
 /* 267 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
 /* 268 */ "trigger_time ::= BEFORE",
 /* 269 */ "trigger_time ::= AFTER",
 /* 270 */ "trigger_time ::= INSTEAD OF",
 /* 271 */ "trigger_time ::=",
 /* 272 */ "trigger_event ::= DELETE|INSERT",
 /* 273 */ "trigger_event ::= UPDATE",
 /* 274 */ "trigger_event ::= UPDATE OF inscollist",
 /* 275 */ "foreach_clause ::=",
 /* 276 */ "foreach_clause ::= FOR EACH ROW",
 /* 277 */ "when_clause ::=",
 /* 278 */ "when_clause ::= WHEN expr",
 /* 279 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
 /* 280 */ "trigger_cmd_list ::= trigger_cmd SEMI",
 /* 281 */ "trnm ::= nm",
 /* 282 */ "trnm ::= nm DOT nm",
 /* 283 */ "tridxby ::=",
 /* 284 */ "tridxby ::= INDEXED BY nm",
 /* 285 */ "tridxby ::= NOT INDEXED",
 /* 286 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
 /* 287 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
 /* 288 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
 /* 289 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
 /* 290 */ "trigger_cmd ::= select",
 /* 291 */ "expr ::= RAISE LP IGNORE RP",
 /* 292 */ "expr ::= RAISE LP raisetype COMMA nm RP",
 /* 293 */ "raisetype ::= ROLLBACK",
 /* 294 */ "raisetype ::= ABORT",
 /* 295 */ "raisetype ::= FAIL",
 /* 296 */ "cmd ::= DROP TRIGGER ifexists fullname",
 /* 297 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
 /* 298 */ "cmd ::= DETACH database_kw_opt expr",
 /* 299 */ "key_opt ::=",
 /* 300 */ "key_opt ::= KEY expr",
 /* 301 */ "database_kw_opt ::= DATABASE",
 /* 302 */ "database_kw_opt ::=",
 /* 303 */ "cmd ::= REINDEX",
 /* 304 */ "cmd ::= REINDEX nm dbnm",
 /* 305 */ "cmd ::= ANALYZE",
 /* 306 */ "cmd ::= ANALYZE nm dbnm",
 /* 307 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
 /* 308 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
 /* 309 */ "add_column_fullname ::= fullname",
 /* 310 */ "kwcolumn_opt ::=",
 /* 311 */ "kwcolumn_opt ::= COLUMNKW",
 /* 312 */ "cmd ::= create_vtab",
 /* 313 */ "cmd ::= create_vtab LP vtabarglist RP",
 /* 314 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
 /* 315 */ "vtabarglist ::= vtabarg",
 /* 316 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
 /* 317 */ "vtabarg ::=",
 /* 318 */ "vtabarg ::= vtabarg vtabargtoken",
 /* 319 */ "vtabargtoken ::= ANY",
 /* 320 */ "vtabargtoken ::= lp anylist RP",
 /* 321 */ "lp ::= LP",
 /* 322 */ "anylist ::=",
 /* 323 */ "anylist ::= anylist LP anylist RP",
 /* 324 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */


#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.
................................................................................
    */
    case 160: /* select */
    case 194: /* oneselect */
{
sqlite3SelectDelete(pParse->db, (yypminor->yy159));
}
      break;
    case 174: /* term */
    case 175: /* expr */
{
sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr);
}
      break;
    case 179: /* idxlist_opt */
    case 187: /* idxlist */
    case 197: /* selcollist */
    case 200: /* groupby_opt */
    case 202: /* orderby_opt */
    case 204: /* sclp */
    case 214: /* sortlist */
    case 215: /* nexprlist */
................................................................................
  { 167, 1 },
  { 167, 4 },
  { 167, 6 },
  { 168, 1 },
  { 168, 2 },
  { 169, 1 },
  { 169, 1 },
  { 164, 3 },
  { 164, 0 },
  { 172, 2 },
  { 172, 0 },
  { 173, 2 },
  { 173, 4 },
  { 173, 3 },
  { 173, 3 },
  { 173, 2 },
  { 173, 2 },
  { 173, 3 },
  { 173, 5 },
  { 173, 2 },
  { 173, 4 },
  { 173, 4 },
  { 173, 1 },
  { 173, 2 },
  { 178, 0 },
  { 178, 1 },
  { 180, 0 },
  { 180, 2 },
  { 182, 2 },
  { 182, 3 },
  { 182, 3 },
  { 182, 3 },
  { 183, 2 },
  { 183, 2 },
  { 183, 1 },
  { 183, 1 },
  { 183, 2 },
  { 181, 3 },
  { 181, 2 },
  { 184, 0 },
  { 184, 2 },
  { 184, 2 },
  { 159, 0 },
  { 159, 2 },


  { 185, 4 },
  { 185, 2 },

  { 186, 7 },
  { 186, 5 },
  { 186, 5 },
  { 186, 10 },
  { 188, 0 },
  { 188, 1 },
  { 176, 0 },
  { 176, 3 },
  { 189, 0 },
  { 189, 2 },
  { 190, 1 },
  { 190, 1 },
  { 190, 1 },
  { 147, 4 },
  { 192, 2 },
................................................................................
  { 209, 2 },
  { 211, 4 },
  { 211, 0 },
  { 202, 0 },
  { 202, 3 },
  { 214, 4 },
  { 214, 2 },
  { 177, 1 },
  { 177, 1 },
  { 177, 0 },
  { 200, 0 },
  { 200, 3 },
  { 201, 0 },
  { 201, 2 },
  { 203, 0 },
  { 203, 2 },
  { 203, 4 },
................................................................................
  { 217, 1 },
  { 219, 4 },
  { 219, 5 },
  { 218, 0 },
  { 218, 3 },
  { 213, 3 },
  { 213, 1 },
  { 175, 1 },
  { 175, 3 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },
  { 175, 3 },
  { 175, 5 },
  { 174, 1 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },
  { 175, 3 },
  { 175, 6 },
  { 175, 5 },
  { 175, 4 },
  { 174, 1 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 221, 1 },
  { 221, 2 },
  { 221, 1 },
  { 221, 2 },
  { 175, 3 },
  { 175, 5 },
  { 175, 2 },
  { 175, 3 },
  { 175, 3 },
  { 175, 4 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 222, 1 },
  { 222, 2 },
  { 175, 5 },
  { 223, 1 },
  { 223, 2 },
  { 175, 5 },
  { 175, 3 },
  { 175, 5 },
  { 175, 4 },
  { 175, 4 },
  { 175, 5 },
  { 225, 5 },
  { 225, 4 },
  { 226, 2 },
  { 226, 0 },
  { 224, 1 },
  { 224, 0 },
  { 220, 1 },
  { 220, 0 },
  { 215, 3 },
  { 215, 1 },
  { 147, 11 },
  { 227, 1 },
  { 227, 0 },
  { 179, 0 },
  { 179, 3 },
  { 187, 5 },
  { 187, 3 },
  { 228, 0 },
  { 228, 2 },
  { 147, 4 },
  { 147, 1 },
  { 147, 2 },
................................................................................
  { 239, 3 },
  { 239, 2 },
  { 237, 7 },
  { 237, 5 },
  { 237, 5 },
  { 237, 5 },
  { 237, 1 },
  { 175, 4 },
  { 175, 6 },
  { 191, 1 },
  { 191, 1 },
  { 191, 1 },
  { 147, 4 },
  { 147, 6 },
  { 147, 3 },
  { 241, 0 },
................................................................................
        break;
      case 13: /* transtype ::= */
{yygotominor.yy392 = TK_DEFERRED;}
        break;
      case 14: /* transtype ::= DEFERRED */
      case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
      case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
      case 113: /* multiselect_op ::= UNION */ yytestcase(yyruleno==113);
      case 115: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==115);
{yygotominor.yy392 = yymsp[0].major;}
        break;
      case 17: /* cmd ::= COMMIT trans_opt */
      case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
{sqlite3CommitTransaction(pParse);}
        break;
      case 19: /* cmd ::= ROLLBACK trans_opt */
................................................................................
{
  pParse->db->lookaside.bEnabled = 0;
  yygotominor.yy0 = yymsp[0].minor.yy0;
}
        break;
      case 28: /* ifnotexists ::= */
      case 31: /* temp ::= */ yytestcase(yyruleno==31);
      case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
      case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
      case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
      case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
      case 96: /* defer_subclause_opt ::= */ yytestcase(yyruleno==96);
      case 107: /* ifexists ::= */ yytestcase(yyruleno==107);
      case 118: /* distinct ::= ALL */ yytestcase(yyruleno==118);
      case 119: /* distinct ::= */ yytestcase(yyruleno==119);
      case 219: /* between_op ::= BETWEEN */ yytestcase(yyruleno==219);
      case 222: /* in_op ::= IN */ yytestcase(yyruleno==222);
{yygotominor.yy392 = 0;}
        break;
      case 29: /* ifnotexists ::= IF NOT EXISTS */
      case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
      case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
      case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
      case 106: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==106);
      case 117: /* distinct ::= DISTINCT */ yytestcase(yyruleno==117);
      case 220: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==220);
      case 223: /* in_op ::= NOT IN */ yytestcase(yyruleno==223);
{yygotominor.yy392 = 1;}
        break;
      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
  sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
}
        break;
................................................................................
  yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}
        break;
      case 37: /* columnid ::= nm */
{
  sqlite3AddColumn(pParse,&yymsp[0].minor.yy0);
  yygotominor.yy0 = yymsp[0].minor.yy0;

}
        break;
      case 38: /* id ::= ID */
      case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
      case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
      case 41: /* nm ::= id */ yytestcase(yyruleno==41);
      case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
      case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
      case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
      case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
      case 125: /* as ::= AS nm */ yytestcase(yyruleno==125);
      case 126: /* as ::= ids */ yytestcase(yyruleno==126);
      case 136: /* dbnm ::= DOT nm */ yytestcase(yyruleno==136);
      case 145: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==145);
      case 248: /* collate ::= COLLATE ids */ yytestcase(yyruleno==248);
      case 257: /* nmnum ::= plus_num */ yytestcase(yyruleno==257);
      case 258: /* nmnum ::= nm */ yytestcase(yyruleno==258);
      case 259: /* nmnum ::= ON */ yytestcase(yyruleno==259);
      case 260: /* nmnum ::= DELETE */ yytestcase(yyruleno==260);
      case 261: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==261);
      case 262: /* plus_num ::= PLUS number */ yytestcase(yyruleno==262);
      case 263: /* plus_num ::= number */ yytestcase(yyruleno==263);
      case 264: /* minus_num ::= MINUS number */ yytestcase(yyruleno==264);
      case 265: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==265);
      case 281: /* trnm ::= nm */ yytestcase(yyruleno==281);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
        break;
      case 45: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
        break;
      case 47: /* typetoken ::= typename LP signed RP */
{
................................................................................
  yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
  yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
        break;
      case 50: /* typename ::= typename ids */
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
        break;
      case 55: /* cname ::= CONSTRAINT nm */

{pParse->constraintName = yymsp[0].minor.yy0;}
        break;
      case 56: /* cname ::= */
{pParse->constraintName.n = 0;}
        break;
      case 57: /* ccons ::= DEFAULT term */
      case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
        break;
      case 58: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);}
        break;
      case 60: /* ccons ::= DEFAULT MINUS term */
{
  ExprSpan v;
  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0);
  v.zStart = yymsp[-1].minor.yy0.z;
  v.zEnd = yymsp[0].minor.yy342.zEnd;
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 61: /* ccons ::= DEFAULT id */
{
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
  sqlite3AddDefaultValue(pParse,&v);
}
        break;
      case 63: /* ccons ::= NOT NULL onconf */
{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);}
        break;
      case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);}
        break;
      case 65: /* ccons ::= UNIQUE onconf */
{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);}
        break;
      case 66: /* ccons ::= CHECK LP expr RP */
{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);}
        break;
      case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);}
        break;
      case 68: /* ccons ::= defer_subclause */
{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);}
        break;
      case 69: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
        break;
      case 72: /* refargs ::= */
{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */}
        break;
      case 73: /* refargs ::= refargs refarg */
{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
        break;
      case 74: /* refarg ::= MATCH nm */
      case 75: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==75);
{ yygotominor.yy207.value = 0;     yygotominor.yy207.mask = 0x000000; }
        break;
      case 76: /* refarg ::= ON DELETE refact */
{ yygotominor.yy207.value = yymsp[0].minor.yy392;     yygotominor.yy207.mask = 0x0000ff; }
        break;
      case 77: /* refarg ::= ON UPDATE refact */
{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8;  yygotominor.yy207.mask = 0x00ff00; }
        break;
      case 78: /* refact ::= SET NULL */
{ yygotominor.yy392 = OE_SetNull;  /* EV: R-33326-45252 */}
        break;
      case 79: /* refact ::= SET DEFAULT */
{ yygotominor.yy392 = OE_SetDflt;  /* EV: R-33326-45252 */}
        break;
      case 80: /* refact ::= CASCADE */
{ yygotominor.yy392 = OE_Cascade;  /* EV: R-33326-45252 */}
        break;
      case 81: /* refact ::= RESTRICT */
{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */}
        break;
      case 82: /* refact ::= NO ACTION */
{ yygotominor.yy392 = OE_None;     /* EV: R-33326-45252 */}
        break;
      case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
      case 97: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==97);
      case 99: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==99);
      case 102: /* resolvetype ::= raisetype */ yytestcase(yyruleno==102);
{yygotominor.yy392 = yymsp[0].minor.yy392;}
        break;
      case 88: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
        break;
      case 89: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
        break;



      case 92: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
        break;
      case 93: /* tcons ::= UNIQUE LP idxlist RP onconf */
{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
        break;
      case 94: /* tcons ::= CHECK LP expr RP onconf */
{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
        break;
      case 95: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
    sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
    sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
}
        break;
      case 98: /* onconf ::= */
{yygotominor.yy392 = OE_Default;}
        break;
      case 100: /* orconf ::= */
{yygotominor.yy258 = OE_Default;}
        break;
      case 101: /* orconf ::= OR resolvetype */
{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
        break;
      case 103: /* resolvetype ::= IGNORE */
{yygotominor.yy392 = OE_Ignore;}
        break;
      case 104: /* resolvetype ::= REPLACE */
{yygotominor.yy392 = OE_Replace;}
        break;
      case 105: /* cmd ::= DROP TABLE ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
}
        break;
      case 108: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
{
  sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
}
        break;
      case 109: /* cmd ::= DROP VIEW ifexists fullname */
{
  sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
}
        break;
      case 110: /* cmd ::= select */
{
  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
  sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
  sqlite3ExplainBegin(pParse->pVdbe);
  sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
  sqlite3ExplainFinish(pParse->pVdbe);
  sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
}
        break;
      case 111: /* select ::= oneselect */
{yygotominor.yy159 = yymsp[0].minor.yy159;}
        break;
      case 112: /* select ::= select multiselect_op oneselect */
{
  if( yymsp[0].minor.yy159 ){
    yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
    yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
  }else{
    sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
  }
  yygotominor.yy159 = yymsp[0].minor.yy159;
}
        break;
      case 114: /* multiselect_op ::= UNION ALL */
{yygotominor.yy392 = TK_ALL;}
        break;
      case 116: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
}
        break;
      case 120: /* sclp ::= selcollist COMMA */
      case 244: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==244);
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
        break;
      case 121: /* sclp ::= */
      case 149: /* orderby_opt ::= */ yytestcase(yyruleno==149);
      case 156: /* groupby_opt ::= */ yytestcase(yyruleno==156);
      case 237: /* exprlist ::= */ yytestcase(yyruleno==237);
      case 243: /* idxlist_opt ::= */ yytestcase(yyruleno==243);
{yygotominor.yy442 = 0;}
        break;
      case 122: /* selcollist ::= sclp expr as */
{
   yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
   if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
   sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
}
        break;
      case 123: /* selcollist ::= sclp STAR */
{
  Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
}
        break;
      case 124: /* selcollist ::= sclp nm DOT STAR */
{
  Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
  Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
}
        break;
      case 127: /* as ::= */
{yygotominor.yy0.n = 0;}
        break;
      case 128: /* from ::= */
{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
        break;
      case 129: /* from ::= FROM seltablist */
{
  yygotominor.yy347 = yymsp[0].minor.yy347;
  sqlite3SrcListShiftJoinType(yygotominor.yy347);
}
        break;
      case 130: /* stl_prefix ::= seltablist joinop */
{
   yygotominor.yy347 = yymsp[-1].minor.yy347;
   if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
}
        break;
      case 131: /* stl_prefix ::= */
{yygotominor.yy347 = 0;}
        break;
      case 132: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
  yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
  sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
}
        break;
      case 133: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
    yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
  }
        break;
      case 134: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
    if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
      yygotominor.yy347 = yymsp[-4].minor.yy347;
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
    }
  }
        break;
      case 135: /* dbnm ::= */
      case 144: /* indexed_opt ::= */ yytestcase(yyruleno==144);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
        break;
      case 137: /* fullname ::= nm dbnm */
{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 138: /* joinop ::= COMMA|JOIN */
{ yygotominor.yy392 = JT_INNER; }
        break;
      case 139: /* joinop ::= JOIN_KW JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
        break;
      case 140: /* joinop ::= JOIN_KW nm JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
        break;
      case 141: /* joinop ::= JOIN_KW nm nm JOIN */
{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
        break;
      case 142: /* on_opt ::= ON expr */
      case 159: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==159);
      case 166: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==166);
      case 232: /* case_else ::= ELSE expr */ yytestcase(yyruleno==232);
      case 234: /* case_operand ::= expr */ yytestcase(yyruleno==234);
{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
        break;
      case 143: /* on_opt ::= */
      case 158: /* having_opt ::= */ yytestcase(yyruleno==158);
      case 165: /* where_opt ::= */ yytestcase(yyruleno==165);
      case 233: /* case_else ::= */ yytestcase(yyruleno==233);
      case 235: /* case_operand ::= */ yytestcase(yyruleno==235);
{yygotominor.yy122 = 0;}
        break;
      case 146: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
        break;
      case 147: /* using_opt ::= USING LP inscollist RP */
      case 178: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==178);
{yygotominor.yy180 = yymsp[-1].minor.yy180;}
        break;
      case 148: /* using_opt ::= */
      case 177: /* inscollist_opt ::= */ yytestcase(yyruleno==177);
{yygotominor.yy180 = 0;}
        break;
      case 150: /* orderby_opt ::= ORDER BY sortlist */
      case 157: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==157);
      case 236: /* exprlist ::= nexprlist */ yytestcase(yyruleno==236);
{yygotominor.yy442 = yymsp[0].minor.yy442;}
        break;
      case 151: /* sortlist ::= sortlist COMMA expr sortorder */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 152: /* sortlist ::= expr sortorder */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
  if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 153: /* sortorder ::= ASC */
      case 155: /* sortorder ::= */ yytestcase(yyruleno==155);
{yygotominor.yy392 = SQLITE_SO_ASC;}
        break;
      case 154: /* sortorder ::= DESC */
{yygotominor.yy392 = SQLITE_SO_DESC;}
        break;
      case 160: /* limit_opt ::= */
{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
        break;
      case 161: /* limit_opt ::= LIMIT expr */
{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
        break;
      case 162: /* limit_opt ::= LIMIT expr OFFSET expr */
{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
        break;
      case 163: /* limit_opt ::= LIMIT expr COMMA expr */
{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
        break;
      case 164: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
  sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
}
        break;
      case 167: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
  sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
  sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); 
  sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
}
        break;
      case 168: /* setlist ::= setlist COMMA nm EQ expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 169: /* setlist ::= nm EQ expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 170: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
        break;
      case 171: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
        break;
      case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
        break;
      case 173: /* insert_cmd ::= INSERT orconf */
{yygotominor.yy258 = yymsp[0].minor.yy258;}
        break;
      case 174: /* insert_cmd ::= REPLACE */
{yygotominor.yy258 = OE_Replace;}
        break;
      case 175: /* valuelist ::= VALUES LP nexprlist RP */
{
  yygotominor.yy487.pList = yymsp[-1].minor.yy442;
  yygotominor.yy487.pSelect = 0;
}
        break;
      case 176: /* valuelist ::= valuelist COMMA LP exprlist RP */
{
  Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
  if( yymsp[-4].minor.yy487.pList ){
    yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
    yymsp[-4].minor.yy487.pList = 0;
  }
  yygotominor.yy487.pList = 0;
................................................................................
    pRight->pPrior = yymsp[-4].minor.yy487.pSelect;
    pRight->selFlags |= SF_Values;
    pRight->pPrior->selFlags |= SF_Values;
    yygotominor.yy487.pSelect = pRight;
  }
}
        break;
      case 179: /* inscollist ::= inscollist COMMA nm */
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
        break;
      case 180: /* inscollist ::= nm */
{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
        break;
      case 181: /* expr ::= term */
{yygotominor.yy342 = yymsp[0].minor.yy342;}
        break;
      case 182: /* expr ::= LP expr RP */
{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 183: /* term ::= NULL */
      case 188: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==188);
      case 189: /* term ::= STRING */ yytestcase(yyruleno==189);
{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
        break;
      case 184: /* expr ::= id */
      case 185: /* expr ::= JOIN_KW */ yytestcase(yyruleno==185);
{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
        break;
      case 186: /* expr ::= nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 187: /* expr ::= nm DOT nm DOT nm */
{
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 190: /* expr ::= REGISTER */
{
  /* When doing a nested parse, one can include terms in an expression
  ** that look like this:   #1 #2 ...  These terms refer to registers
  ** in the virtual machine.  #N is the N-th register. */
  if( pParse->nested==0 ){
    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
    yygotominor.yy342.pExpr = 0;
................................................................................
  }else{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
    if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
  }
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 191: /* expr ::= VARIABLE */
{
  spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
  sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 192: /* expr ::= expr COLLATE ids */
{
  yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 193: /* expr ::= CAST LP expr AS typetoken RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 194: /* expr ::= ID LP distinct exprlist RP */
{
  if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
  }
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
  if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 195: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
  spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 196: /* term ::= CTIME_KW */
{
  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
  ** treated as functions that return constants */
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->op = TK_CONST_FUNC;  
  }
  spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 197: /* expr ::= expr AND expr */
      case 198: /* expr ::= expr OR expr */ yytestcase(yyruleno==198);
      case 199: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==199);
      case 200: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==200);
      case 201: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==201);
      case 202: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==202);
      case 203: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==203);
      case 204: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==204);
{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
        break;
      case 205: /* likeop ::= LIKE_KW */
      case 207: /* likeop ::= MATCH */ yytestcase(yyruleno==207);
{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
        break;
      case 206: /* likeop ::= NOT LIKE_KW */
      case 208: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==208);
{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
        break;
      case 209: /* expr ::= expr likeop expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
  if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 210: /* expr ::= expr likeop expr ESCAPE expr */
{
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
  if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
  if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 211: /* expr ::= expr ISNULL|NOTNULL */
{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
        break;
      case 212: /* expr ::= expr NOT NULL */
{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
        break;
      case 213: /* expr ::= expr IS expr */
{
  spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
}
        break;
      case 214: /* expr ::= expr IS NOT expr */
{
  spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
}
        break;
      case 215: /* expr ::= NOT expr */
      case 216: /* expr ::= BITNOT expr */ yytestcase(yyruleno==216);
{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 217: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 218: /* expr ::= PLUS expr */
{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
        break;
      case 221: /* expr ::= expr between_op expr AND expr */
{
  ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->x.pList = pList;
  }else{
................................................................................
    sqlite3ExprListDelete(pParse->db, pList);
  } 
  if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
  yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
  yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
}
        break;
      case 224: /* expr ::= expr in_op LP exprlist RP */
{
    if( yymsp[-1].minor.yy442==0 ){
      /* Expressions of the form
      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
................................................................................
      }
      if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    }
    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 225: /* expr ::= LP select RP */
{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 226: /* expr ::= expr in_op LP select RP */
{
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
    }else{
................................................................................
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 227: /* expr ::= expr in_op nm dbnm */
{
    SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
    yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
    if( yygotominor.yy342.pExpr ){
      yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
      ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
................................................................................
      sqlite3SrcListDelete(pParse->db, pSrc);
    }
    if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
    yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
    yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
  }
        break;
      case 228: /* expr ::= EXISTS LP select RP */
{
    Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
    if( p ){
      p->x.pSelect = yymsp[-1].minor.yy159;
      ExprSetProperty(p, EP_xIsSelect);
      sqlite3ExprSetHeight(pParse, p);
    }else{
      sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
    }
    yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
    yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 229: /* expr ::= CASE case_operand case_exprlist case_else END */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
    sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
  }else{
    sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442);
  }
  yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 230: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 231: /* case_exprlist ::= WHEN expr THEN expr */
{
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 238: /* nexprlist ::= nexprlist COMMA expr */
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
        break;
      case 239: /* nexprlist ::= expr */
{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
        break;
      case 240: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
  sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, 
                     sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
                      &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
}
        break;
      case 241: /* uniqueflag ::= UNIQUE */
      case 294: /* raisetype ::= ABORT */ yytestcase(yyruleno==294);
{yygotominor.yy392 = OE_Abort;}
        break;
      case 242: /* uniqueflag ::= */
{yygotominor.yy392 = OE_None;}
        break;
      case 245: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
  sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 246: /* idxlist ::= nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
    sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
  sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
  sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
  if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
}
        break;
      case 247: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
        break;
      case 249: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
        break;
      case 250: /* cmd ::= VACUUM */
      case 251: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==251);
{sqlite3Vacuum(pParse);}
        break;
      case 252: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
        break;
      case 253: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
        break;
      case 254: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
        break;
      case 255: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
        break;
      case 256: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
        break;
      case 266: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
  Token all;
  all.z = yymsp[-3].minor.yy0.z;
  all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
  sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
}
        break;
      case 267: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
  sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
  yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
        break;
      case 268: /* trigger_time ::= BEFORE */
      case 271: /* trigger_time ::= */ yytestcase(yyruleno==271);
{ yygotominor.yy392 = TK_BEFORE; }
        break;
      case 269: /* trigger_time ::= AFTER */
{ yygotominor.yy392 = TK_AFTER;  }
        break;
      case 270: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy392 = TK_INSTEAD;}
        break;
      case 272: /* trigger_event ::= DELETE|INSERT */
      case 273: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==273);
{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
        break;
      case 274: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
        break;
      case 277: /* when_clause ::= */
      case 299: /* key_opt ::= */ yytestcase(yyruleno==299);
{ yygotominor.yy122 = 0; }
        break;
      case 278: /* when_clause ::= WHEN expr */
      case 300: /* key_opt ::= KEY expr */ yytestcase(yyruleno==300);
{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
        break;
      case 279: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
  assert( yymsp[-2].minor.yy327!=0 );
  yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
  yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
  yygotominor.yy327 = yymsp[-2].minor.yy327;
}
        break;
      case 280: /* trigger_cmd_list ::= trigger_cmd SEMI */
{ 
  assert( yymsp[-1].minor.yy327!=0 );
  yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
  yygotominor.yy327 = yymsp[-1].minor.yy327;
}
        break;
      case 282: /* trnm ::= nm DOT nm */
{
  yygotominor.yy0 = yymsp[0].minor.yy0;
  sqlite3ErrorMsg(pParse, 
        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
        "statements within triggers");
}
        break;
      case 284: /* tridxby ::= INDEXED BY nm */
{
  sqlite3ErrorMsg(pParse,
        "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 285: /* tridxby ::= NOT INDEXED */
{
  sqlite3ErrorMsg(pParse,
        "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 286: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
        break;
      case 287: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
        break;
      case 288: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
        break;
      case 289: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
        break;
      case 290: /* trigger_cmd ::= select */
{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
        break;
      case 291: /* expr ::= RAISE LP IGNORE RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
  if( yygotominor.yy342.pExpr ){
    yygotominor.yy342.pExpr->affinity = OE_Ignore;
  }
  yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 292: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
  yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
  if( yygotominor.yy342.pExpr ) {
    yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
  }
  yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
  yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 293: /* raisetype ::= ROLLBACK */
{yygotominor.yy392 = OE_Rollback;}
        break;
      case 295: /* raisetype ::= FAIL */
{yygotominor.yy392 = OE_Fail;}
        break;
      case 296: /* cmd ::= DROP TRIGGER ifexists fullname */
{
  sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
}
        break;
      case 297: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
  sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
}
        break;
      case 298: /* cmd ::= DETACH database_kw_opt expr */
{
  sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
}
        break;
      case 303: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
        break;
      case 304: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 305: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
        break;
      case 306: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 307: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
  sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
}
        break;
      case 308: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
  sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
        break;
      case 309: /* add_column_fullname ::= fullname */
{
  pParse->db->lookaside.bEnabled = 0;
  sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
}
        break;
      case 312: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
        break;
      case 313: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
        break;
      case 314: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
    sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
}
        break;
      case 317: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
        break;
      case 319: /* vtabargtoken ::= ANY */
      case 320: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==320);
      case 321: /* lp ::= LP */ yytestcase(yyruleno==321);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
        break;
      default:
      /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
      /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
      /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
      /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
................................................................................
      /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
      /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
      /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
      /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
      /* (44) type ::= */ yytestcase(yyruleno==44);
      /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
      /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
      /* (53) carglist ::= carglist cname ccons */ yytestcase(yyruleno==53);
      /* (54) carglist ::= */ yytestcase(yyruleno==54);
      /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);

      /* (90) conslist ::= conslist COMMA cname tcons */ yytestcase(yyruleno==90);
      /* (91) conslist ::= cname tcons */ yytestcase(yyruleno==91);
      /* (275) foreach_clause ::= */ yytestcase(yyruleno==275);
      /* (276) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==276);
      /* (283) tridxby ::= */ yytestcase(yyruleno==283);
      /* (301) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==301);
      /* (302) database_kw_opt ::= */ yytestcase(yyruleno==302);
      /* (310) kwcolumn_opt ::= */ yytestcase(yyruleno==310);
      /* (311) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==311);
      /* (315) vtabarglist ::= vtabarg */ yytestcase(yyruleno==315);
      /* (316) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==316);
      /* (318) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==318);
      /* (322) anylist ::= */ yytestcase(yyruleno==322);
      /* (323) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==323);
      /* (324) anylist ::= anylist ANY */ yytestcase(yyruleno==324);
        break;
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
  if( yyact < YYNSTATE ){
................................................................................
** name of a directory, then that directory will be used to store
** temporary files.
**
** See also the "PRAGMA temp_store_directory" SQL command.
*/
SQLITE_API char *sqlite3_temp_directory = 0;










/*
** Initialize SQLite.  
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystems prior to doing any serious work with
** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
................................................................................
  if( sqlite3GlobalConfig.isPCacheInit ){
    sqlite3PcacheShutdown();
    sqlite3GlobalConfig.isPCacheInit = 0;
  }
  if( sqlite3GlobalConfig.isMallocInit ){
    sqlite3MallocEnd();
    sqlite3GlobalConfig.isMallocInit = 0;












  }
  if( sqlite3GlobalConfig.isMutexInit ){
    sqlite3MutexEnd();
    sqlite3GlobalConfig.isMutexInit = 0;
  }

  return SQLITE_OK;
................................................................................
    pDestructor->nRef--;
    if( pDestructor->nRef==0 ){
      pDestructor->xDestroy(pDestructor->pUserData);
      sqlite3DbFree(db, pDestructor);
    }
  }
}

/*
** Close an existing SQLite database

*/
SQLITE_API int sqlite3_close(sqlite3 *db){
  HashElem *i;                    /* Hash table iterator */
























  int j;













  if( !db ){
    return SQLITE_OK;
  }
  if( !sqlite3SafetyCheckSickOrOk(db) ){
    return SQLITE_MISUSE_BKPT;
  }
  sqlite3_mutex_enter(db->mutex);

  /* Force xDestroy calls on all virtual tables */
  sqlite3ResetInternalSchema(db, -1);

  /* If a transaction is open, the ResetInternalSchema() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()
  ** call will do so. We need to do this before the check for active
  ** SQL statements below, as the v-table implementation may be storing
  ** some prepared statements internally.
  */
  sqlite3VtabRollback(db);

  /* If there are any outstanding VMs, return SQLITE_BUSY. */
  if( db->pVdbe ){


    sqlite3Error(db, SQLITE_BUSY, 
        "unable to close due to unfinalised statements");

    sqlite3_mutex_leave(db->mutex);
    return SQLITE_BUSY;
  }
  assert( sqlite3SafetyCheckSickOrOk(db) );

  for(j=0; j<db->nDb; j++){
    Btree *pBt = db->aDb[j].pBt;
    if( pBt && sqlite3BtreeIsInBackup(pBt) ){

      sqlite3Error(db, SQLITE_BUSY, 
          "unable to close due to unfinished backup operation");

































      sqlite3_mutex_leave(db->mutex);
      return SQLITE_BUSY;
    }
  }






  /* Free any outstanding Savepoint structures. */
  sqlite3CloseSavepoints(db);


  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pBt ){
      sqlite3BtreeClose(pDb->pBt);
      pDb->pBt = 0;
      if( j!=1 ){
        pDb->pSchema = 0;
      }
    }
  }
  sqlite3ResetInternalSchema(db, -1);










  /* Tell the code in notify.c that the connection no longer holds any
  ** locks and does not require any further unlock-notify callbacks.
  */
  sqlite3ConnectionClosed(db);

  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(j=0; j<ArraySize(db->aFunc.a); j++){
    FuncDef *pNext, *pHash, *p;
    for(p=db->aFunc.a[j]; p; p=pHash){
      pHash = p->pHash;
      while( p ){
        functionDestroy(db, p);
        pNext = p->pNext;
................................................................................
  db->magic = SQLITE_MAGIC_CLOSED;
  sqlite3_mutex_free(db->mutex);
  assert( db->lookaside.nOut==0 );  /* Fails on a lookaside memory leak */
  if( db->lookaside.bMalloced ){
    sqlite3_free(db->lookaside.pStart);
  }
  sqlite3_free(db);
  return SQLITE_OK;
}

/*
** Rollback all database files.  If tripCode is not SQLITE_OK, then
** any open cursors are invalidated ("tripped" - as in "tripping a circuit
** breaker") and made to return tripCode if there are any further
** attempts to use that cursor.
................................................................................
    }
  }
  sqlite3VtabRollback(db);
  sqlite3EndBenignMalloc();

  if( db->flags&SQLITE_InternChanges ){
    sqlite3ExpirePreparedStatements(db);
    sqlite3ResetInternalSchema(db, -1);
  }

  /* Any deferred constraint violations have now been resolved. */
  db->nDeferredCons = 0;

  /* If one has been configured, invoke the rollback-hook callback */
  if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
................................................................................
          zModeType = "cache";
        }
        if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
          static struct OpenMode aOpenMode[] = {
            { "ro",  SQLITE_OPEN_READONLY },
            { "rw",  SQLITE_OPEN_READWRITE }, 
            { "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },

            { 0, 0 }
          };

          mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;

          aMode = aOpenMode;
          limit = mask & flags;
          zModeType = "access";
        }

        if( aMode ){
          int i;
................................................................................
            }
          }
          if( mode==0 ){
            *pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
            rc = SQLITE_ERROR;
            goto parse_uri_out;
          }
          if( mode>limit ){
            *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
                                        zModeType, zVal);
            rc = SQLITE_PERM;
            goto parse_uri_out;
          }
          flags = (flags & ~mask) | mode;
        }
................................................................................

  }else{
    zFile = sqlite3_malloc(nUri+2);
    if( !zFile ) return SQLITE_NOMEM;
    memcpy(zFile, zUri, nUri);
    zFile[nUri] = '\0';
    zFile[nUri+1] = '\0';

  }

  *ppVfs = sqlite3_vfs_find(zVfs);
  if( *ppVfs==0 ){
    *pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
    rc = SQLITE_ERROR;
  }
................................................................................

SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *);

SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart(
    Fts3Table*, Fts3MultiSegReader*, int, const char*, int);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
    Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *);
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol); 
SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);

SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);








#endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */
#endif /* _FTSINT_H */

/************** End of fts3Int.h *********************************************/
/************** Continuing where we left off in fts3.c ***********************/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
................................................................................
**
** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed
** to by the argument to point to the "simple" tokenizer implementation.
** And so on.
*/
SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule);
SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule);



#ifdef SQLITE_ENABLE_ICU
SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule);
#endif

/*
** Initialise the fts3 extension. If this extension is built as part
** of the sqlite library, then this function is called directly by
................................................................................
** function is called by the sqlite3_extension_init() entry point.
*/
SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
  int rc = SQLITE_OK;
  Fts3Hash *pHash = 0;
  const sqlite3_tokenizer_module *pSimple = 0;
  const sqlite3_tokenizer_module *pPorter = 0;




#ifdef SQLITE_ENABLE_ICU
  const sqlite3_tokenizer_module *pIcu = 0;
  sqlite3Fts3IcuTokenizerModule(&pIcu);
#endif





#ifdef SQLITE_TEST
  rc = sqlite3Fts3InitTerm(db);
  if( rc!=SQLITE_OK ) return rc;
#endif

  rc = sqlite3Fts3InitAux(db);
................................................................................
    sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
  }

  /* Load the built-in tokenizers into the hash table */
  if( rc==SQLITE_OK ){
    if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
     || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) 




#ifdef SQLITE_ENABLE_ICU
     || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
#endif
    ){
      rc = SQLITE_NOMEM;
    }
  }
................................................................................
*/
SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(
  int bDescIdx,                   /* True if the doclist is desc */
  char *aDoclist,                 /* Pointer to entire doclist */
  int nDoclist,                   /* Length of aDoclist in bytes */
  char **ppIter,                  /* IN/OUT: Iterator pointer */
  sqlite3_int64 *piDocid,         /* IN/OUT: Docid pointer */
  int *pnList,                    /* IN/OUT: List length pointer */
  u8 *pbEof                       /* OUT: End-of-file flag */
){
  char *p = *ppIter;

  assert( nDoclist>0 );
  assert( *pbEof==0 );
  assert( p || *piDocid==0 );
................................................................................
      char *pSave = p;
      fts3ReversePoslist(aDoclist, &p);
      *pnList = (int)(pSave - p);
    }
    *ppIter = p;
  }
}




































/*
** Attempt to move the phrase iterator to point to the next matching docid. 
** If an error occurs, return an SQLite error code. Otherwise, return 
** SQLITE_OK.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
................................................................................
** for 'X' is requested, the buffer returned may contain:
**
**     0x04 0x05 0x03 0x01   or   0x04 0x05 0x03 0x00
**
** This function works regardless of whether or not the phrase is deferred,
** incremental, or neither.
*/
SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(
  Fts3Cursor *pCsr,               /* FTS3 cursor object */
  Fts3Expr *pExpr,                /* Phrase to return doclist for */
  int iCol                        /* Column to return position list for */

){
  Fts3Phrase *pPhrase = pExpr->pPhrase;
  Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
  char *pIter = pPhrase->doclist.pList;
  int iThis;





  assert( iCol>=0 && iCol<pTab->nColumn );
  if( !pIter 
   || pExpr->bEof 
   || pExpr->iDocid!=pCsr->iPrevId
   || (pPhrase->iColumn<pTab->nColumn && pPhrase->iColumn!=iCol) 
  ){
    return 0;
  }





































  assert( pPhrase->doclist.nList>0 );
























  if( *pIter==0x01 ){
    pIter++;
    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
  }else{
    iThis = 0;
  }
  while( iThis<iCol ){
    fts3ColumnlistCopy(0, &pIter);
    if( *pIter==0x00 ) return 0;
    pIter++;
    pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
  }

  return ((iCol==iThis)?pIter:0);

}

/*
** Free all components of the Fts3Phrase structure that were allocated by
** the eval module. Specifically, this means to free:
**
**   * the contents of pPhrase->doclist, and
................................................................................

/* #include <tcl.h> */
/* #include <string.h> */

/*
** Implementation of a special SQL scalar function for testing tokenizers 
** designed to be used in concert with the Tcl testing framework. This
** function must be called with two arguments:
**
**   SELECT <function-name>(<key-name>, <input-string>);
**   SELECT <function-name>(<key-name>, <pointer>);
**
** where <function-name> is the name passed as the second argument
** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer')
** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test').
**
** The return value is a string that may be interpreted as a Tcl
** list. For each token in the <input-string>, three elements are
................................................................................
  const char *zErr = 0;

  const char *zName;
  int nName;
  const char *zInput;
  int nInput;

  const char *zArg = 0;

  const char *zToken;
  int nToken;
  int iStart;
  int iEnd;
  int iPos;


  Tcl_Obj *pRet;

  assert( argc==2 || argc==3 );




  nName = sqlite3_value_bytes(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[0]);
  nInput = sqlite3_value_bytes(argv[argc-1]);
  zInput = (const char *)sqlite3_value_text(argv[argc-1]);

  if( argc==3 ){
    zArg = (const char *)sqlite3_value_text(argv[1]);
  }

  pHash = (Fts3Hash *)sqlite3_user_data(context);
  p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);

  if( !p ){
    char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
    return;
  }

  pRet = Tcl_NewObj();
  Tcl_IncrRefCount(pRet);





  if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){
    zErr = "error in xCreate()";
    goto finish;
  }
  pTokenizer->pModule = p;
  if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){
    zErr = "error in xOpen()";
    goto finish;
................................................................................
    rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0);
  }
  if( SQLITE_OK==rc ){
    rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0);
  }
#ifdef SQLITE_TEST
  if( SQLITE_OK==rc ){
    rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0);
  }
  if( SQLITE_OK==rc ){
    rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0);
  }
  if( SQLITE_OK==rc ){
    rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0);
  }
#endif

#ifdef SQLITE_TEST
................................................................................
**
**   fts3SegReaderNext()
**   fts3SegReaderFirstDocid()
**   fts3SegReaderNextDocid()
*/
struct Fts3SegReader {
  int iIdx;                       /* Index within level, or 0x7FFFFFFF for PT */

  int bLookup;                    /* True for a lookup only */

  sqlite3_int64 iStartBlock;      /* Rowid of first leaf block to traverse */
  sqlite3_int64 iLeafEndBlock;    /* Rowid of final leaf block to traverse */
  sqlite3_int64 iEndBlock;        /* Rowid of final block in segment (or 0) */
  sqlite3_int64 iCurrentBlock;    /* Current leaf block (or 0) */

  char *aNode;                    /* Pointer to node data (or NULL) */
................................................................................
  */
  char *pOffsetList;
  int nOffsetList;                /* For descending pending seg-readers only */
  sqlite3_int64 iDocid;
};

#define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0)
#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1])

/*
** An instance of this structure is used to create a segment b-tree in the
** database. The internal details of this type are only accessed by the
** following functions:
**
**   fts3SegWriterAdd()
................................................................................

  pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
  if( !pReader ){
    return SQLITE_NOMEM;
  }
  memset(pReader, 0, sizeof(Fts3SegReader));
  pReader->iIdx = iAge;
  pReader->bLookup = bLookup;
  pReader->iStartBlock = iStartLeaf;
  pReader->iLeafEndBlock = iEndLeaf;
  pReader->iEndBlock = iEndBlock;

  if( nExtra ){
    /* The entire segment is stored in the root node. */
    pReader->aNode = (char *)&pReader[1];

    pReader->nNode = nRoot;
    memcpy(pReader->aNode, zRoot, nRoot);
    memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING);
  }else{
    pReader->iCurrentBlock = iStartLeaf-1;
  }
  *ppReader = pReader;
................................................................................
  if( sqlite3_step(pStmt)==SQLITE_ROW ){
    fts3DecodeIntArray(nStat, a,
         sqlite3_column_blob(pStmt, 0),
         sqlite3_column_bytes(pStmt, 0));
  }else{
    memset(a, 0, sizeof(u32)*(nStat) );
  }
  sqlite3_reset(pStmt);





  if( nChng<0 && a[0]<(u32)(-nChng) ){
    a[0] = 0;
  }else{
    a[0] += nChng;
  }
  for(i=0; i<p->nColumn+1; i++){
    u32 x = a[i+1];
................................................................................
** This function is an fts3ExprIterate() callback used by fts3BestSnippet().
** Each invocation populates an element of the SnippetIter.aPhrase[] array.
*/
static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
  SnippetIter *p = (SnippetIter *)ctx;
  SnippetPhrase *pPhrase = &p->aPhrase[iPhrase];
  char *pCsr;


  pPhrase->nToken = pExpr->pPhrase->nToken;

  pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);

  if( pCsr ){
    int iFirst = 0;
    pPhrase->pList = pCsr;
    fts3GetDeltaPosition(&pCsr, &iFirst);
    assert( iFirst>=0 );
    pPhrase->pHead = pCsr;
    pPhrase->pTail = pCsr;
    pPhrase->iHead = iFirst;
    pPhrase->iTail = iFirst;
  }else{

    assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 );

  }

  return SQLITE_OK;
}

/*
** Select the fragment of text consisting of nFragment contiguous tokens 
** from column iCol that represent the "best" snippet. The best snippet
** is the snippet with the highest score, where scores are calculated
** by adding:
................................................................................
** array that are different for each row returned by the query.
*/
static int fts3ExprLocalHitsCb(
  Fts3Expr *pExpr,                /* Phrase expression node */
  int iPhrase,                    /* Phrase number */
  void *pCtx                      /* Pointer to MatchInfo structure */
){

  MatchInfo *p = (MatchInfo *)pCtx;
  int iStart = iPhrase * p->nCol * 3;
  int i;

  for(i=0; i<p->nCol; i++){
    char *pCsr;
    pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i);
    if( pCsr ){
      p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr);
    }else{
      p->aMatchinfo[iStart+i*3] = 0;
    }
  }

  return SQLITE_OK;
}

static int fts3MatchinfoCheck(
  Fts3Table *pTab, 
  char cArg,
  char **pzErr
){
................................................................................
  }

  for(iCol=0; iCol<pInfo->nCol; iCol++){
    int nLcs = 0;                 /* LCS value for this column */
    int nLive = 0;                /* Number of iterators in aIter not at EOF */

    for(i=0; i<pInfo->nPhrase; i++){

      LcsIterator *pIt = &aIter[i];
      pIt->pRead = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol);

      if( pIt->pRead ){
        pIt->iPos = pIt->iPosOffset;
        fts3LcsIteratorAdvance(&aIter[i]);
        nLive++;
      }
    }

................................................................................
*/
static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
  TermOffsetCtx *p = (TermOffsetCtx *)ctx;
  int nTerm;                      /* Number of tokens in phrase */
  int iTerm;                      /* For looping through nTerm phrase terms */
  char *pList;                    /* Pointer to position list for phrase */
  int iPos = 0;                   /* First position in position-list */


  UNUSED_PARAMETER(iPhrase);
  pList = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol);
  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;
  }

  return SQLITE_OK;
}

/*
** Implementation of offsets() function.
*/
SQLITE_PRIVATE void sqlite3Fts3Offsets(
  sqlite3_context *pCtx,          /* SQLite function call context */
................................................................................
    sqlite3_result_blob(pContext, pCsr->aMatchinfo, n, SQLITE_TRANSIENT);
  }
}

#endif

/************** End of fts3_snippet.c ****************************************/



























































































































































































































































































































































































































































































































































































































































































































































































/************** Begin file rtree.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
................................................................................
    rc = nodeRelease(pRtree, pRoot);
  }else{
    nodeRelease(pRtree, pRoot);
  }

  return rc;
}































/*
** The xUpdate method for rtree module virtual tables.
*/
static int rtreeUpdate(
  sqlite3_vtab *pVtab, 
  int nData, 
................................................................................
    int ii;

    /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
    assert( nData==(pRtree->nDim*2 + 3) );
#ifndef SQLITE_RTREE_INT_ONLY
    if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
      for(ii=0; ii<(pRtree->nDim*2); ii+=2){
        cell.aCoord[ii].f = (RtreeValue)sqlite3_value_double(azData[ii+3]);
        cell.aCoord[ii+1].f = (RtreeValue)sqlite3_value_double(azData[ii+4]);
        if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
          rc = SQLITE_CONSTRAINT;
          goto constraint;
        }
      }
    }else
#endif
................................................................................
    iEnd = ubrk_next(pCsr->pIter);
    if( iEnd==UBRK_DONE ){
      return SQLITE_DONE;
    }

    while( iStart<iEnd ){
      int iWhite = iStart;
      U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
      if( u_isspace(c) ){
        iStart = iWhite;
      }else{
        break;
      }
    }
    assert(iStart<=iEnd);


|







 







>













|
>
>
>
|
>
|
>

|
>
>
>







 







|
>
>
>
|
<
>
>
|




>
>
>







 







|
|
|







 







>
|







 







>
|
|
|
>

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

|
<
>
>
>

|


|
>



|
|

|
>







 







>







 







>







 







|







 







|



|
|







 







|
|
>






|
>
|
|
<
>







 







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







 







<







 







<







|
|
|







 







|







 







|







 







|









<
<










<
<
<
<
<



<



<







<
<
<


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







 







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







 







<
<









<
<







 







>







 







>
>


<
<
|
<
<


>
>
>
>
>
>
>
>







 







>
|
>







 







>







 







>







 







>
>
>







 







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