fnc

Check-in Differences
Login

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

Difference From 0.15 To 0.16

2023-11-26 11:53
bump version number: 0.17 (check-in: 720ac95e45 user: mark tags: trunk)
2023-11-26 11:24
CHANGES for 0.16 (check-in: dce24e7685 user: mark tags: trunk, 0.16)
2023-11-25 10:48
allow stash operations involving empty tracked files (check-in: a2c542f43c user: mark tags: trunk)
2023-04-20 12:10
bump version number: 0.16 (check-in: e515c79492 user: mark tags: trunk)
2023-04-20 12:08
CHANGES for 0.15 (check-in: 4e2b3d91eb user: mark tags: trunk, 0.15)
2023-04-20 11:55
latest upstream libfossil 231fed953330909f (check-in: 6e23d39e0c user: mark tags: trunk)

Changes to .editorconfig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14

1
2
3
4
5
6
7
8
9
10
11
12
13

14













-
+
# EditorConfig (https://editorconfig.com) Configuration for fnc
#
# Following https://fossil-scm.org/fossil/doc/trunk/www/style.wiki

# Defaults for all files
[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 8

[{Makefile,Makefile.*,*.make,*.make.in}]
indent_style = tab
indent_size = 4
indent_size = 8

Changes to CHANGES.md.










































































1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**fnc 0.16** 2023-11-26 [[history][0.16a] / [diff][0.16b]]

- drop unnecessary sqlite3 extensions
- refactor cli and replace bespoke argument parser with getopt(3)
- refactor repository and checkout database initialisation
- replace `malloc(n * size)` idiom with reallocarray(3) or calloc(3)
- check a couple missed strdup(3) instances for failure
- completely disable landlock on linux when invoking `fnc stash` commands
- fix `fnc tree -c commit` segv when `commit` is an empty tree (initial commit)
- attempt to detect symlinks via F cards when building trees from the repo db
- allow blaming symlinks from tree view if fossil(1)'s `allow-symlinks` is set
- fix potential off-by-one error in ISO 8601 timestamp macro
- fix incorrect logic in work tree root path validation
- implement client-side error handling instead of the library's `fsl_error` API
- fix timeline view horizontal scrolling bug that could garble the view
- report "no changes in the diff requested" instead of showing an empty diff
- add `ccdb` make target to the build system to generate a compilation database
- plug commit id leak in the blame view
- drop ugly diff view 'F' keymap; the ^n/^p keymaps make it all but redundant
- implement diffstat to show histogram of total lines added/removed in the diff
- improve diffs involving renamed files with fossil(1) `fossil mv`
- refactor diff navigation code, API, and manifest parser
- discern aborted from completed stash commands with no hunks selected to stash
- guard against a `line_type` array OOB read when parsing new wiki commits
- improve rendering of tag and ticket artifacts in the diff view
- make '$' keymap scroll to the longest line on the page, not the whole buffer
- align branch id hashes in branch views the same way it's done in tree views
- don't fatally error when non-checkin artifacts are tagged in the timeline
- fix timeline tagging (space keymap) regression from [2d681fc13] that would  
  fatally error when tagging non-checkin (e.g., wiki) artifacts to diff
- allow all commit artifacts (e.g., tag, technote, wiki) as `log -c` arguments
- used fixed-size buffer for commit id SHA hashes
- fix diff view regression from [2d681fc13] that broke diffs between blobs
- miscellaneous documentation improvements in fnc(1) man page and `-h` output
- implement `fnc diff -o` to write diff to stdout without rendering in curses
- make 'n' and 'N' respect the current line position when resuming search
- silently ignore illegal `FNC_VIEW_SPLIT_HEIGHT` values; fallback to default
- guard against out-of-bounds access on empty `optarg` string
- catched missed fclose(3) and unlink(2) calls for failure
- fix NULL pointer dereference in new `fnc diff -o artifact1 artifact2` case
- swap behaviour of the diff view j/k and ^e/^y keymaps
- make 'Q' a valid interactive stash answer to abort without opening help view
- expand diffstat to display in all diff types (i.e., blobs, commits, worktree)
- annotate the checked-out commit to show work tree state in the timeline view
- restore ability to use work tree root, not just cwd, relative paths
- check for and rollback any unlikely open database transactions on exit
- plug leak of char pointer in fnc_file_artifact struct in diff cleanup
- zap unnecessary path allocation in the blame view
- include diffstat and commit metadata in diffs written with the 'P' keymap
- fix changeset line duplication bug when regenerating diffs between blobs
- plug `wchar_t` pointer leak of the diff headline in new `fnc diff -o` case
- fix 'v' keymap to not incorrectly hide diff content in diffs of blobs
- replace fseek(3) with fseeko(3)
- add a tree entry/line index to the tree view headline
- latest upstream libfossil with integer overflow fix [libf:ef095328f]
- fix gcc 11.2.0 compiler warnings (maybe-uninitialised)
- refactor stash implementation
- make `fnc diff` respect fossil(1)'s `allow-symlinks` setting
- make the new `ccdb` makefile target work with macOS bsdmake(1)
- fix redefined variable guarded by platform dependent ifdef
- fix runtime help regression on wide terminals introduced in [0d3e7424d4]
- kill raw mode on wgetnstr(3) input to restore echo(3) behaviour on OpenBSD
- update in-tree sqlite to 3.45.0
- fix regression introduced by unveiling `TMPDIR` rather than `P_tmpdir` in  
  [aae8e777f], which broke tmpfile(3) and mkstemp(3) calls
- zap redundant header
- merge upstream libfossil with gcc 13.2.1 build errors and delta creation fix
- tweaks for successful patch-free builds on all architectures in alpine linux  
  ci with `-Os -fstack-clash-protection -Wformat -Werror=format-security`
- fix `fnc blame -r` regression introduced in [aae8e777f]
- fix undefined behaviour (double-free) when releasing view resources
- allow stash operations involving zero-length blobs (empty tracked files)

**fnc 0.15** 2023-04-20 [[history][0.15a] / [diff][0.15b]]

- update in-tree sqlite to 3.42.0 to fix unused-but-set clang 14.03 build error
- latest upstream libfossil with fixes for clang 14.03 build errors

**fnc 0.14** 2023-04-18 [[history][0.14a] / [diff][0.14b]]

318
319
320
321
322
323
324


325
326
327
328
329
330
331
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406







+
+







- wrap commit comments to the current view width
- implement cmd_diff() to provide the 'fnc diff' interface
- tailor help/usage output to the specified command
- fix invalid memory read in diff routine
- add support for repository fingerprint version 1
- fix line wrap bug that truncated lines in fullscreen mode

[0.16a]: https://fnc.bsdbox.org/timeline?p=0.16&bt=0.15
[0.16b]: https://fnc.bsdbox.org/vdiff?from=0.15&to=0.16
[0.15a]: https://fnc.bsdbox.org/timeline?p=0.15&bt=0.14
[0.15b]: https://fnc.bsdbox.org/vdiff?from=0.14&to=0.15
[0.14a]: https://fnc.bsdbox.org/timeline?p=0.14&bt=0.13
[0.14b]: https://fnc.bsdbox.org/vdiff?from=0.13&to=0.14
[0.13a]: https://fnc.bsdbox.org/timeline?p=0.13&bt=0.12
[0.13b]: https://fnc.bsdbox.org/vdiff?from=0.12&to=0.13
[0.12a]: https://fnc.bsdbox.org/timeline?p=0.12&bt=0.11

Changes to GNUmakefile.

11
12
13
14
15
16
17





11
12
13
14
15
16
17
18
19
20
21
22







+
+
+
+
+
ifeq ($(UNAME),Darwin)
# OSX
FNC_LDFLAGS +=	-lncurses -lpanel -liconv
else
# Linux (tested on Debian), OpenBSD, FreeBSD
FNC_LDFLAGS +=	-lncursesw -lpanelw
endif

# make ccdb: clang compilation database build
ifdef CCDB
CFLAGS +=	-MJ ccdb/$(@F:.o=.o.json)
endif

Changes to Makefile.

11
12
13
14
15
16
17






11
12
13
14
15
16
17
18
19
20
21
22
23







+
+
+
+
+
+
.if $(UNAME) == Darwin
# OSX
FNC_LDFLAGS +=	-lncurses -lpanel -liconv
.else
# Linux (tested on Debian), OpenBSD, FreeBSD
FNC_LDFLAGS +=	-lncursesw -lpanelw
.endif

# make ccdb: clang compilation database build
.if defined(CCDB)
FILESEGMENT =	$(.TARGET:C/$(@D)//)
CFLAGS +=	-MJ ccdb$(FILESEGMENT:=.json)
.endif

Changes to README.md.

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







# README

# fnc: an interactive text-based user interface for [Fossil]

`fnc` uses [ncurses] and [libfossil] to create a [`fossil ui`][fui] experience
in the terminal, and parse local changes at the hunk level to prepare atomic
commits.

Tested and confirmed to run on the following amd64 systems (additional
platforms noted inline):

1. OpenBSD 6.8-, 6.9-, 7.0-, 7.1-, and 7.2-{current,release}
1. OpenBSD 6.8 through 7.3-{current,release}
2. macOS Catalina 10.15.7, Big Sur 11.5.2, and Ventura 13.0.1
3. Linux Mint 20.2 (32- and 64-bit ARM)
4. Ubuntu 18.04, 21.04, 21.10, and 22.04 running Linux 5.1{1,3} (32-bit ARM)
5. Debian GNU/Linux 8, 9, and 10
6. CentOS 6.5 (32-bit)

Alpha development notwithstanding, the `timeline`, `diff`, `tree`, `blame`,
29
30
31
32
33
34
35

36

37
38
39
40
41
42
43
44
45
46
47
48



49
50
51
52
53
54
55
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58







+
-
+











-
+
+
+







* **FreeBSD**
  - <u>package</u>: `pkg install fnc`
  - <u>port</u>: `cd /usr/ports/devel/fnc/ && make install clean`
* **NixOS**
  - `nix-env -iA nixos.fnc`
* **Alpine Linux**
  - `apk add fnc`  
  n.b. ensure _testing_ repository is enabled
  n.b. Ensure _testing_ repository is enabled (see <https://wiki.alpinelinux.org/wiki/Repositories#Testing>)
  (see <https://wiki.alpinelinux.org/wiki/Repositories#Testing>)

Check [repology] to find if a package is provided for your operating system.
If no package exists, [download] and install the binary on your path.

# Build

1. clone the repository
  - `fossil clone https://fnc.bsdbox.org`
2. move into the repository checkout
  - `cd fnc`
3. build fnc
  - `make`
  - `make`  
  n.b. if compiling with clang, `make ccdb` can be used to generate a
  compilation database (`compile_commands.json`) for your [language server][lsp]
4. install the `fnc` binary (*requires privileges*)
  - `doas make install`
5. move into an open Fossil checkout, and run it:
  - `cd ~/museum/repo && fossil open ../repo.fossil && fnc`

This will install the `fnc` executable and man page into `/usr/local/bin` and
`/usr/local/share/man/man1`, respectively. Alternatively, cryptographically
136
137
138
139
140
141
142

143
144
145
146
147
148
149
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153







+







[email]:	mailto:fnc@bsdbox.org
[fnc(1)]:	https://fnc.bsdbox.org/uv/doc/fnc.1.html
[forum]:	https://fnc.bsdbox.org/forum
[Fossil]:	https://fossil-scm.org
[fui]:		https://fossil-scm.org/home/help?cmd=ui
[Got]:		https://gameoftrees.org
[libfossil]:	https://fossil.wanderinghorse.net/r/libfossil
[lsp]:		https://clangd.llvm.org
[mailing list]:	https://itac.bsdbox.org/listinfo/fnc
[ncurses]:	https://invisible-island.net/ncurses/ncurses.html
[repology]:	https://repology.org/project/fnc/versions
[style(9)]:	https://man.openbsd.org/style.9
[ticket]:	https://fnc.bsdbox.org/ticket
[`tog`]:	https://gameoftrees.org/tog.1.html
[`P` keymap]:	https://fnc.bsdbox.org/uv/doc/fnc.1.html#P~3

Deleted compile_flags.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-std=c89
-I
include
-I
lib
-isystem
/usr/local/include
-isystem
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include
-isystem
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
-isystem
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
-isystem
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks

Changes to fnc.bld.mk.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16








-
+







#
# FNC Common Build
#

# CONFIGURATION
CC ?=		cc
PREFIX ?=	/usr/local
MANDIR ?=	/share/man
VERSION ?=	0.15
VERSION ?=	0.16
HASH !=		cut -f 1 manifest.uuid
DATE !=		sed '2q;d' manifest | cut -d ' ' -f 2 | tr T ' '

# FLAGS NEEDED TO BUILD SQLITE3
SQLITE_CFLAGS =	${CFLAGS} -Wall -Werror -Wno-sign-compare -pedantic -std=c99 \
		-DNDEBUG=1 \
		-DSQLITE_DQS=0 \
58
59
60
61
62
63
64
65


66
67
68
69
70
71


















72

73
74
75
76
77
78
79
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99







-
+
+






+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+








lib/libfossil.o: lib/libfossil.c lib/libfossil.h
	${CC} ${FOSSIL_CFLAGS} -c $< -o $@

src/diff.o: src/diff.c include/diff.h
	${CC} ${FNC_CFLAGS} -c $< -o $@

src/fnc.o: src/fnc.c include/settings.h include/diff.h fnc.bld.mk
src/fnc.o: src/fnc.c include/diff.h include/enum.h include/error.h \
	include/fnc.h include/opt.h fnc.bld.mk
	${CC} ${FNC_CFLAGS} -c $< -o $@

src/fnc: src/fnc.o src/diff.o lib/libfossil.o lib/sqlite3.o fnc.bld.mk
	${CC} -o $@ src/fnc.o src/diff.o lib/libfossil.o lib/sqlite3.o \
	${FNC_LDFLAGS}

ccdb: clean
	@$(CC) -v 2>&1 | grep clang; \
	if [ $$? -ne 0 ]; then \
		echo "clang needed to generate compilation database"; \
		exit 1; \
	fi
	@-rm -rf $@
	@mkdir $@
	${MAKE} CCDB=1
	@-rm -f compile_commands.json
	@{ \
		echo [; \
		cat $@/*.o.json | tr '\n' ' ' | sed -e 's/, $$//'; \
		echo ]; \
	} > compile_commands.json
	@-rm -rf $@
	@echo "generated compile_commands.json"

install:
	mkdir -p -m 0755 ${PREFIX}/bin
	mkdir -p -m 0755 ${PREFIX}${MANDIR}/man1
	install -s -m 0755 src/fnc ${PREFIX}/bin/fnc
	install -m 0644 src/fnc.1 ${PREFIX}${MANDIR}/man1/fnc.1

uninstall:
	rm -f ${PREFIX}/bin/fnc ${PREFIX}${MANDIR}/man1/fnc.1

Changes to include/diff.h.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39




































40
41
42
43
44
45



46
47
48
49
50
51
52
53
54
55
56


















57
58
59
60
61
62
63
64



65
66
67
68
69
70
71
72
73
74
75

76
77
78

79
80
81


82
83

84
85
86
87
88
89


90
91
92
93
94
95
96



97
98

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17
18
19
20
21
22














23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61



62
63
64
65










66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83





84


85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100

101
102


103
104
105

106
107
108
109
110


111
112
113
114
115
116



117
118
119
120

121

-
+














-
-
-






-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



-
-
-
+
+
+

-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-

-
-
+
+
+










-
+


-
+

-
-
+
+

-
+




-
-
+
+




-
-
-
+
+
+

-
+
/*
 * Copyright (c) 2022 Mark Jamsek <mark@bsdbox.org>
 * Copyright (c) 2022, 2023 Mark Jamsek <mark@bsdbox.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "libfossil.h"
#include "settings.h"

/*
 * Flags set by callers of the below diff APIs to determine diff output.
 */
enum fnc_diff_flag {
	FNC_DIFF_IGNORE_EOLWS	= 0x01,
	FNC_DIFF_IGNORE_ALLWS	= 0x03,
	FNC_DIFF_SIDEBYSIDE	= 1 << 2,  /* output side-by-side diff */
	FNC_DIFF_VERBOSE	= 1 << 3,  /* show added/rm'd file content */
	FNC_DIFF_BRIEF		= 1 << 4,  /* no content, just index lines */
	FNC_DIFF_HTML		= 1 << 5,
	FNC_DIFF_LINENO		= 1 << 6,  /* show file line numbers */
	FNC_DIFF_NOOPT		= 1 << 8,  /* suppress optimisations (debug) */
	FNC_DIFF_INVERT		= 1 << 9,
	FNC_DIFF_PROTOTYPE	= 1 << 10, /* show scope in hunk header */
	FNC_DIFF_NOTTOOBIG	= 1 << 11, /* don't compute "large" diffs */
	FNC_DIFF_STRIP_EOLCR	= 1 << 12, /* strip trailing '\r' */
	FNC_DIFF_ANSI_COLOR	= 1 << 13
#define FNC_DIFF_CONTEXT_EX	(((uint64_t)0x04) << 32)  /* Allow 0 context */
#define FNC_DIFF_CONTEXT_MASK	((uint64_t)0x0000ffff)    /* Default context */
#define FNC_DIFF_WIDTH_MASK	((uint64_t)0x00ff0000)    /* SBS column width */
	FNC_DIFF_SIDEBYSIDE	= (1 << 2),
	FNC_DIFF_VERBOSE	= (1 << 3),  /* show added/rm'd file content */
	FNC_DIFF_BRIEF		= (1 << 4),  /* no content, just index lines */
	FNC_DIFF_HTML		= (1 << 5),
	FNC_DIFF_LINENO		= (1 << 6),  /* show file line numbers */
	FNC_DIFF_STATMIN	= (1 << 7),  /* show minimal diffstat */
	FNC_DIFF_NOOPT		= (1 << 8),  /* no optimisations (debug) */
	FNC_DIFF_INVERT		= (1 << 9),
	FNC_DIFF_PROTOTYPE	= (1 << 10), /* show scope in hunk header */
	FNC_DIFF_NOTTOOBIG	= (1 << 11), /* don't compute "large" diffs */
	FNC_DIFF_STRIP_EOLCR	= (1 << 12), /* strip trailing '\r' */
	FNC_DIFF_ANSI_COLOR	= (1 << 13)
#define FNC_DIFF_CONTEXT_EX	(((uint64_t)0x04) << 32) /* allow 0 context */
#define FNC_DIFF_CONTEXT_MASK	((uint64_t)0x0000ffff)	 /* default context */
#define FNC_DIFF_WIDTH_MASK	((uint64_t)0x00ff0000)	 /* SBS column width */
};

enum line_type {
	LINE_BLANK,
	LINE_TIMELINE_HEADER,
	LINE_TIMELINE_COMMIT,
	LINE_DIFF_ARTIFACT,
	LINE_DIFF_USER,
	LINE_DIFF_TAGS,
	LINE_DIFF_DATE,
	LINE_DIFF_COMMENT,
	LINE_DIFF_CHANGESET,
	LINE_DIFF_INDEX,
	LINE_DIFF_HEADER,
	LINE_DIFF_META,
	LINE_DIFF_MINUS,
	LINE_DIFF_PLUS,
	LINE_DIFF_EDIT,
	LINE_DIFF_CONTEXT,
	LINE_DIFF_HUNK,
	LINE_DIFF_SEPARATOR
};

/*
 * Compute the diff of changes to convert the file in fsl_buffer parameter 1
 * to the file in fsl_buffer parameter 2 and save the result to the provided
 * output fsl_buffer in parameter 3.
 * Compute the diff of changes to convert the file in fsl_buffer parameter 2
 * to the file in fsl_buffer parameter 3 and save the result to the provided
 * output fsl_buffer in parameter 1.
 *
 * A unified diff is output by default. This, along with other diff options
 * (detailed in the above fnc_diff_flag enum), can be changed by setting the
 * corresponding flags passed in int parameter 8.
 *
 * If a unified diff, parameter 7 is ignored, and the number of context lines
 * is specified in short parameter 6. Negative values fallback to default. If
 * a side-by-side diff, parameter 6 is ignored, and the column width of each
 * side is specified in short parameter 7; only values larger than the longest
 * line are honoured, otherwise the column width of each side will
 * automatically grow to accommodate the longest line in the diff.
 * A unified diff is output by default. Alternatively, a side-by-side diff
 * along with other changes (documented in the fnc_diff_flag enum) can be
 * produced by setting the corresponding flags passed in int parameter 9.

 * If not NULL, the enum array pointer in paramater 4 and size_t pointer in
 * parameter 5 will be populated with each line_type and the total number of
 * lines written out to the diff, respectively. The enum array and output
 * buffer can be prepopulated with the size_t value inidicating the prefilled
 * line count; the former two must be disposed of by the caller. The uint64_t
 * pointer in parameter 6 will be encoded with the total number of added and
 * removed lines in the low and high 32 bits, respectively.
 *
 * If a unified diff, parameter 8 is ignored, and the number of context lines
 * is specified in short parameter 7; negative values fallback to default. If
 * a side-by-side diff, parameter 7 is ignored, and the column width of each
 * side is specified in short parameter 8; only values larger than the longest
 * line are honoured, otherwise the column width of each side will be sized
 * large enough to accommodate the longest line in the diff.

 * If not NULL, the enum array pointer in paramater 4 and uint32_t pointer in
 * parameter 5 will be populated with each line_type and the total number of
 * lines in the diff, respectively.  Both pointers and the output buffer can
 * be prepopulated and must be disposed of by the caller.
 */
int fnc_diff_text_to_buffer(const fsl_buffer *, const fsl_buffer *,
    fsl_buffer *, enum line_type **, uint32_t *, short, short, int);
int fnc_diff_text_to_buffer(fsl_buffer *, const fsl_buffer *,
    const fsl_buffer *, enum line_type **, size_t *, uint64_t *,
    short, short, int);

/*
 * Compute the diff of changes to convert the file in fsl_buffer parameter 1
 * to the file in fsl_buffer parameter 2 and invoke the fsl_output_f callback
 * in parameter 3 for each computed line.  The callback receives the provided
 * void parameter 4 as its output state and a char pointer of the diffed line
 * or diff metadata (e.g., hunk header, index).  Remaining parameters are the
 * same as the above fnc_diff_text_to_buffer() routine.
 */
int fnc_diff_text(const fsl_buffer *, const fsl_buffer *, fsl_output_f, void *,
    enum line_type **, uint32_t *, short, short, int);
    enum line_type **, size_t *, uint64_t *, short, short, int);

/*
 * Compute and save to the int array pointer in parameter 4 the array of
 * Compute and save to the int array pointer in out parameter 1 the array of
 * copy/delete/insert triples that describes the sequence of changes to convert
 * the file in fsl_buffer parameter 1 to the file in fsl_buffer parameter 2.
 * Diff format and related options are set via flags passed in int parameter 3.
 * the file in fsl_buffer parameter 2 to the file in fsl_buffer parameter 3.
 * Diff format and related options are set via flags passed in int parameter 4.
 */
int fnc_diff_text_raw(const fsl_buffer *, const fsl_buffer *, int, int **);
int fnc_diff_text_raw(int **, const fsl_buffer *, const fsl_buffer *, int);

/*
 * Return the number of columns required to draw to the screen the char pointer
 * in parameter 1 by expanding any tabs and accounting for unicode continuation
 * bytes. Short parameter 2 may either be the byte size of the string or
 * a negative value.
 * bytes. Short parameter 2 may either be the byte size of the string or less
 * than zero, in which case the string length will be computed with strlen(3).
 */
unsigned short etcount(const char *, unsigned short);

/*
 * Save the line_type specified in parameter 3 to the nth index denoted by the
 * uint32_t pointer in parameter 2 of the line_type array in parameter 1. The
 * uint32_t value pointed to by the 2nd parameter will be incremented.
 * Save the line_type specified in parameter 3 to the nth index denoted by
 * the size_t pointer in parameter 2 of the line_type array in parameter 1.
 * The size_t index pointed to by the 2nd parameter will be incremented.
 */
int add_line_type(enum line_type **, uint32_t *, enum line_type);
int add_line_type(enum line_type **, size_t *, enum line_type);

Added include/enum.h.
























































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2021, 2022, 2023 Mark Jamsek <mark@jamsek.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define GEN_ENUM_SYM(pfx, id)	pfx##_##id
#define GEN_ENUM(name, pfx, info)				\
	enum name { info(pfx, GEN_ENUM_SYM) };

#define GEN_STR_SYM(pfx, id)	#pfx"_"#id
#define GEN_STR(name, pfx, info)				\
	const char *name[] = { info(pfx, GEN_STR_SYM) };

/*
 * All configurable fnc settings, which can be stored in either the fossil(1)
 * repository (e.g., ./repo.fossil) or shell envvars with `export SETTING=val`.
 */
#define USER_OPTIONS(pfx, _)					\
	_(pfx, START_SETTINGS),					\
	_(pfx, COLOUR_COMMIT),					\
	_(pfx, COLOUR_USER),					\
	_(pfx, COLOUR_DATE),					\
	_(pfx, COLOUR_DIFF_META),				\
	_(pfx, COLOUR_DIFF_MINUS),				\
	_(pfx, COLOUR_DIFF_PLUS),				\
	_(pfx, COLOUR_DIFF_HUNK),				\
	_(pfx, COLOUR_DIFF_TAGS),				\
	_(pfx, COLOUR_DIFF_SBS_EDIT),				\
	_(pfx, COLOUR_TREE_LINK),				\
	_(pfx, COLOUR_TREE_DIR),				\
	_(pfx, COLOUR_TREE_EXEC),				\
	_(pfx, COLOUR_BRANCH_OPEN),				\
	_(pfx, COLOUR_BRANCH_CLOSED),				\
	_(pfx, COLOUR_BRANCH_CURRENT),				\
	_(pfx, COLOUR_BRANCH_PRIVATE),				\
	_(pfx, COLOUR_HL_LINE),					\
	_(pfx, COLOUR_HL_SEARCH),				\
	_(pfx, DIFF_CONTEXT),					\
	_(pfx, DIFF_FLAGS),					\
	_(pfx, VIEW_SPLIT_MODE),				\
	_(pfx, VIEW_SPLIT_WIDTH),				\
	_(pfx, VIEW_SPLIT_HEIGHT),				\
	_(pfx, EOF_SETTINGS)

#define LINE_ATTR_ENUM(pfx, _)					\
	_(pfx, AUTO),						\
	_(pfx, MONO)

#define INPUT_TYPE_ENUM(pfx, _)					\
	_(pfx, ALPHA),						\
	_(pfx, NUMERIC)

#define VIEW_MODE_ENUM(pfx, _)					\
	_(pfx, NONE),						\
	_(pfx, VERT),						\
	_(pfx, HRZN)

#define STASH_MVMT_ENUM(pfx, _)					\
	_(pfx, NONE),						\
	_(pfx, DOWN),						\
	_(pfx, UP),						\
	_(pfx, UPDOWN)

/*
 * XXX Must be sorted lexicographically for fnc_command_lookup().
 */
#define VIEW_ID_ENUM(pfx, _)					\
	_(pfx, BLAME),						\
	_(pfx, BRANCH),						\
	_(pfx, CONFIG),						\
	_(pfx, DIFF),						\
	_(pfx, STASH),						\
	_(pfx, TIMELINE),					\
	_(pfx, TREE)

#define SEARCH_MVMT_ENUM(pfx, _)				\
	_(pfx, DONE),						\
	_(pfx, FORWARD),					\
	_(pfx, REVERSE)

#define SEARCH_STATE_ENUM(pfx, _)				\
	_(pfx, WAITING),					\
	_(pfx, CONTINUE),					\
	_(pfx, COMPLETE),					\
	_(pfx, NO_MATCH),					\
	_(pfx, ABORTED),					\
	_(pfx, FOR_END)

#define DIFF_TYPE_ENUM(pfx, _)					\
	_(pfx, CKOUT),						\
	_(pfx, COMMIT),						\
	_(pfx, BLOB),						\
	_(pfx, WIKI)

#define DIFF_MODE_ENUM(pfx, _)					\
	_(pfx, NORMAL),						\
	_(pfx, META),						\
	_(pfx, STASH)

#define DIFF_HUNK_ENUM(pfx, _)					\
	_(pfx, NONE),						\
	_(pfx, STASH),						\
	_(pfx, CKOUT)

#define PATCH_RC_ENUM(pfx, _)					\
	_(pfx, OK),						\
	_(pfx, MALFORMED),					\
	_(pfx, TRUNCATED),					\
	_(pfx, NOT_FOUND),					\
	_(pfx, HUNK_FAILED),					\
	_(pfx, FAILED)

#define STASH_OPT_ENUM(pfx, _)					\
	_(pfx, NONE),		/* reset sticky answer */	\
	_(pfx, KEEP_FILE),	/* keep hunks left in file */	\
	_(pfx, KEEP_ALL),	/* keep all hunks left */	\
	_(pfx, STASH_FILE),	/* stash hunks left in file */	\
	_(pfx, STASH_ALL)	/* stash all hunks left */

#define ENUM_INFO(_)						\
	_(fnc_opt_id, FNC, USER_OPTIONS)			\
	_(line_attr, SLINE, LINE_ATTR_ENUM)			\
	_(input_type, INPUT, INPUT_TYPE_ENUM)			\
	_(view_mode, VIEW_SPLIT, VIEW_MODE_ENUM)		\
	_(stash_mvmt, STASH_MVMT, STASH_MVMT_ENUM)		\
	_(fnc_view_id, FNC_VIEW, VIEW_ID_ENUM)			\
	_(fnc_search_mvmt, SEARCH, SEARCH_MVMT_ENUM)		\
	_(fnc_search_state, SEARCH, SEARCH_STATE_ENUM)		\
	_(fnc_diff_type, FNC_DIFF, DIFF_TYPE_ENUM)		\
	_(fnc_diff_mode, DIFF_MODE, DIFF_MODE_ENUM)		\
	_(fnc_diff_hunk, HUNK, DIFF_HUNK_ENUM)			\
	_(fnc_patch_rc, PATCH, PATCH_RC_ENUM)			\
	_(stash_opt, STASH_CH, STASH_OPT_ENUM)

#define GEN_ENUMS(name, pfx, info) GEN_ENUM(name, pfx, info)
ENUM_INFO(GEN_ENUMS)

#define STR_INFO(_) _(fnc_opt_name, FNC, USER_OPTIONS)
#define GEN_STRINGS(name, pfx, info) GEN_STR(name, pfx, info)
STR_INFO(GEN_STRINGS)

Added include/error.h.

































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2023 Mark Jamsek <mark@jamsek.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* Error result codes cannot exceed 100 (which is where libf codes begin). */
#define FNC_RC_OK		0
#define FNC_RC_ERROR		1
#define FNC_RC_BREAK		2
#define FNC_RC_CANCELLED	3
#define FNC_RC_NO_CKOUT		4
#define FNC_RC_NO_REPO		5
#define FNC_RC_NO_MATCH		6
#define FNC_RC_ERRNO		7
#define FNC_RC_BAD_PATH		8
#define FNC_RC_NO_REPO_PATH	9
#define FNC_RC_NO_CKOUT_PATH	10
#define FNC_RC_NO_TREE_PATH	11
#define FNC_RC_NO_BRANCH	12
#define FNC_RC_NO_USER		13
#define FNC_RC_NO_TAG		14
#define FNC_RC_NO_RID		15
#define FNC_RC_NO_COMMIT	16
#define FNC_RC_NO_REF		17
#define FNC_RC_BAD_HASH		18
#define FNC_RC_BAD_ARTIFACT	19
#define FNC_RC_AMBIGUOUS_ID	20
#define FNC_RC_EMPTY_TREE	21
#define FNC_RC_IO		22
#define FNC_RC_EOF		23
#define FNC_RC_NO_SPACE		24
#define FNC_RC_RANGE		25
#define FNC_RC_BAD_OPTION	26
#define FNC_RC_BAD_CMD		27
#define FNC_RC_AMBIGUOUS_CMD	28
#define FNC_RC_CKOUT_BUSY	29
#define FNC_RC_NYI		30
#define FNC_RC_BAD_KEYWORD	31
#define FNC_RC_DIFF_BINARY	32
#define FNC_RC_BLAME_BINARY	33
#define FNC_RC_AMBIGUOUS_DATE	34
#define FNC_RC_BAD_DATE		35
#define FNC_RC_REGEX		36
#define FNC_RC_CURSES		37
#define FNC_RC_FATAL		38
#define FNC_RC_SITREP		39
#define FNC_RC_BAD_NUMBER	40

struct fnc_error {
	int		 rc;
	const char	*msg;
};

/* Private implementation. */
#ifdef __OpenBSD__
#define FNC_ERRNO_STR_SZ	NL_TEXTMAX
#else
#define FNC_ERRNO_STR_SZ	1024
#endif

#define FNC_ERR_PREFIX_SZ	1024
#define FNC_ERR_MSG_BUFSZ	(FNC_ERR_PREFIX_SZ + FNC_ERRNO_STR_SZ)

#if DEBUG
#define RC_SET(_r, _fmt, ...)	fsl_error_set(&fnc__error, _r, "%s::%s " _fmt,\
				    __func__, FILE_POSITION, __VA_ARGS__)
#else
#define RC_SET(_r, _fmt, ...)	fsl_error_set(&fnc__error, _r, _fmt,	\
				    __VA_ARGS__)
#endif /* DEBUG */

#define RCX(_r, ...)	_r == FNC_RC_ERRNO ? RC_ERRNO(__VA_ARGS__) :		\
			    _r == FNC_RC_BREAK ? RC_BREAK(__VA_ARGS__) :	\
			    _r >= FSL_RC_ERROR ? RC_LIBF(_r, __VA_ARGS__) :	\
			    RC_SET(_r, "%s", fnc_error(_r, __VA_ARGS__))

/* Public API */

/*
 * Set the error state to result code rc with a message built from the
 * optional provided format string and variable length argument list,
 * which will be prefixed with rc's corresponding error message mapped
 * from the below list. FNC_RC_ERRNO, FNC_RC_BREAK, and valid fsl_rc_e
 * FSL_RC_* enum result codes are special cases with slightly different
 * semantics per the below documented RC_ERRNO, RC_BREAK, and RC_LIBF API.
 *	RC(rc)
 *	RC(rc, fmt, ...)
 */
#define RC(...)	RCX(__VA_ARGS__, "", 0)

/*
 * Set the error state to FNC_RC_ERRNO, with a message built from the
 * provided format string and variable length argument list, which will
 * be suffixed with an errno error string obtained from strerror(3).
 */
#define RC_ERRNO(...)	RC_SET(FNC_RC_ERRNO, "%s",			\
			    fnc_error_from_errno(__VA_ARGS__))

/*
 * Set errno to _e and the error state to FNC_RC_ERRNO, with a message built
 * from the provided format string and variable length argument list, which
 * will be suffixed with an errno error string obtained from strerror(3).
 */
#define RC_ERRNO_SET(_e, ...)	RC((errno =_e) == FNC_RC_OK ?		\
				    FNC_RC_ERROR : FNC_RC_ERRNO,	\
				    "%s", __VA_ARGS__)

/*
 * Set the error state based on the error indicator for file stream _f
 * as returned by ferror(3): either the RC_ERRNO or RC macro will be used
 * if the indicator is set or unset, respectively, with the resulting
 * message built per the corresponding API as documented above.
 */
#define RC_FERROR(_f, ...)	ferror(_f) ?				\
				    RC_ERRNO(__VA_ARGS__) :		\
				    RC_SET(FNC_RC_EOF, __VA_ARGS__, "")

/*
 * Set the error state to FNC_RC_BREAK, a special case used to report
 * that the requested operation cannot proceed due to unmet preconditions
 * (e.g., different artifacts selected from the timeline view to diff),
 * but will not fatally error. This is often used to report such cases
 * before resuming the view loop, and to return zero on exit with a message
 * built from the provided format string and variable length argument list.
 */
#define RC_BREAK(...)	RC_SET(FNC_RC_BREAK, __VA_ARGS__, "")

/*
 * Set the error state to _e, where _e is a valid fsl_rc_e FSL_RC_* enum
 * error code, with a message built from the provided format string and
 * variable length argument list, prefixed by a libfossil error obtained
 * from fsl_error_get() or fsl_rc_cstr() via fnc_error_from_libf().
 */
#define RC_LIBF(_e, ...) RC_SET(_e, "%s", fnc_error_from_libf(_e, __VA_ARGS__))

/* Reset the error state. */
#define RC_RESET()	fnc_error_reset()

/* Error strings cannot exceed FNC_ERRNO_STR_SZ (OpenBSD: 255, Linux: 1024). */
#define GENERATE_ERROR_MAP \
	ERR_(FNC_RC_OK,			NULL),					\
	ERR_(FNC_RC_ERROR,		NULL),					\
	ERR_(FNC_RC_BREAK,		NULL),					\
	ERR_(FNC_RC_CANCELLED,		"operation in progress cancelled"),	\
	ERR_(FNC_RC_NO_CKOUT,		"no work tree found"),			\
	ERR_(FNC_RC_NO_REPO,		"no fossil repository found"),		\
	ERR_(FNC_RC_NO_MATCH,		"no matches found"),			\
	ERR_(FNC_RC_ERRNO,		NULL),					\
	ERR_(FNC_RC_BAD_PATH,		"invalid path"),			\
	ERR_(FNC_RC_NO_REPO_PATH,	"path not found in the repository"),	\
	ERR_(FNC_RC_NO_CKOUT_PATH,	"path not found in the checkout"),	\
	ERR_(FNC_RC_NO_TREE_PATH,	"path not found in tree"),		\
	ERR_(FNC_RC_NO_BRANCH,		"branch not found"),			\
	ERR_(FNC_RC_NO_USER,		"user not found"),			\
	ERR_(FNC_RC_NO_TAG,		"tag not found"),			\
	ERR_(FNC_RC_NO_RID,		"rid not found in the database"),	\
	ERR_(FNC_RC_NO_COMMIT,		"commit not found"),			\
	ERR_(FNC_RC_NO_REF,		"no such reference found"),		\
	ERR_(FNC_RC_BAD_HASH,		"invalid SHA hash"),			\
	ERR_(FNC_RC_BAD_ARTIFACT,	"bad artifact type"),			\
	ERR_(FNC_RC_AMBIGUOUS_ID,	"ambiguous artifact id"),		\
	ERR_(FNC_RC_EMPTY_TREE,		"tree is empty"),			\
	ERR_(FNC_RC_IO,			"input/output error"),			\
	ERR_(FNC_RC_EOF,		"unexpected end of file"),		\
	ERR_(FNC_RC_NO_SPACE,		"buffer too small"),			\
	ERR_(FNC_RC_RANGE,		"value out of range"),			\
	ERR_(FNC_RC_BAD_OPTION,		"invalid option"),			\
	ERR_(FNC_RC_BAD_CMD,		"invalid command"),			\
	ERR_(FNC_RC_AMBIGUOUS_CMD,	"ambiguous command"),			\
	ERR_(FNC_RC_CKOUT_BUSY,		"checkout database is locked"),		\
	ERR_(FNC_RC_NYI,		"feature is not implemented"),		\
	ERR_(FNC_RC_BAD_KEYWORD,	"invalid keyword"),			\
	ERR_(FNC_RC_DIFF_BINARY,	"cannot diff binary file"),		\
	ERR_(FNC_RC_BLAME_BINARY,	"cannot blame binary file"),		\
	ERR_(FNC_RC_AMBIGUOUS_DATE,	"ambiguous date"),			\
	ERR_(FNC_RC_BAD_DATE,		"invalid date"),			\
	ERR_(FNC_RC_REGEX,		"regular expression error"),		\
	ERR_(FNC_RC_CURSES,		"fatal curses error"),			\
	ERR_(FNC_RC_FATAL,		"unexpected fatality"),			\
	ERR_(FNC_RC_SITREP,		NULL),					\
	ERR_(FNC_RC_BAD_NUMBER,		"invalid number")

Added include/fnc.h.



























































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2021, 2022, 2023 Mark Jamsek <mark@jamsek.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define FNC_VERSION	VERSION  /* cf. Makefile */
#define FNC_HASH	HASH
#define FNC_DATE	DATE

#ifdef FCLI_USE_SIGACTION
#define FCLI_USE_SIGACTION 0	/* we want ^c to exit */
#endif

/* Utility macros. */
#define MIN(_a, _b)	((_a) < (_b) ? (_a) : (_b))
#define MAX(_a, _b)	((_a) > (_b) ? (_a) : (_b))
#define ABS(_n)		((_n) >= 0 ? (_n) : -(_n))
#ifndef CTRL
#define CTRL(key)	((key) & 037)	/* ^key input */
#endif
#define nitems(_a)		(sizeof((_a)) / sizeof((_a)[0]))
#define ndigits(_d, _n)		do { _d++; } while (_n /= 10)
#define STRINGIFYOUT(_s)	#_s
#define STRINGIFY(_s)		STRINGIFYOUT(_s)
#define CONCATOUT(_a, _b)	_a ## _b
#define CONCAT(_a, _b)		CONCATOUT(_a, _b)
#define FILE_POSITION		__FILE__ ":" STRINGIFY(__LINE__)
#define FLAG_SET(_f, _b)	((_f) |= (_b))
#define FLAG_CHK(_f, _b)	((_f) & (_b))
#define FLAG_TOG(_f, _b)	((_f) ^= (_b))
#define FLAG_CLR(_f, _b)	((_f) &= ~(_b))

/* Application macros. */
#define PRINT_VERSION	STRINGIFY(FNC_VERSION)
#define PRINT_HASH	STRINGIFY(FNC_HASH)
#define PRINT_DATE	STRINGIFY(FNC_DATE)
#define DEF_DIFF_CTX	5		/* Default diff context lines. */
#define MAX_DIFF_CTX	64		/* Max diff context lines. */
#define HSPLIT_SCALE	0.4		/* Default horizontal split scale. */
#define SPIN_INTERVAL	200		/* Status line progress indicator. */
#define LINENO_WIDTH	6		/* View lineno max column width. */
#define MAX_PCT_LEN	7		/* Line position upto max len 99.99% */
#define SPINNER		"\\|/-\0"
#define NULL_DEVICE	"/dev/null"
#define NULL_DEVICELEN	(sizeof(NULL_DEVICE) - 1)
#define KEY_ESCAPE	27

/* fossil(1) db and runtime related paths to unveil() */
#define REPODB		fsl_cx_db_file_repo(fcli_cx(), NULL)
#define REPODIR		getdirname(REPODB, -1, false)
#define CKOUTDIR	fsl_cx_ckout_dir_name(fcli_cx(), NULL)
#ifdef P_tmpdir
const char *tmpdir = P_tmpdir;
#elif defined(_PATH_TMP)
const char *tmpdir = _PATH_TMP;
#else
const char *tmpdir = "/tmp/";
#endif

/* Portability macros. */
#ifdef __linux__
#ifndef HAVE_STRTONUM	/* use strtoll and a range check to emulate strtonum */
#define INRANGE(n_, min_, max_)						\
	(n_ < min_ || n_ > max_) ||					\
	(errno == ERANGE && (n_ == LLONG_MIN || n_ == LLONG_MAX)) ?	\
	n_ == (errno = ERANGE) : n_
#define strtonum(s_, m_, x_, e_) INRANGE((strtoll(s_, (char **)e_, 10)), m_, x_)
#endif /* HAVE_STRTONUM */
#ifndef HAVE_BSD_STRING
#define strlcat(_d, _s, _sz) fsl_strlcat(_d, _s, _sz)
#define strlcpy(_d, _s, _sz) fsl_strlcpy(_d, _s, _sz)
#endif /* HAVE_BSD_STRING */
#if defined(_DEFAULT_SOURCE) || defined(_GNU_SOURCE)
#define HAVE_REALLOCARRAY
#endif
#elif !defined(__APPLE__) /* XXX Do all BSDs have reallocarray(3)? */
#define HAVE_REALLOCARRAY
#endif /* __linux__ */

#define PRINTFV(fmt, args) __attribute__((format (printf, fmt, args)))
#ifndef __dead
#define __dead	__attribute__((noreturn))
#endif

#ifndef __predict_true
# ifdef __has_builtin
#  if __has_builtin(__builtin_expect)
#   define __predict_true(_e)	__builtin_expect(((_e) != 0), 1)
#   define __predict_false(_e)	__builtin_expect(((_e) != 0), 0)
#  endif
# endif
#endif
#ifndef __predict_true
# define __predict_true(_e)	((_e) != 0)
# define __predict_false(_e)	((_e) != 0)
#endif

#ifndef TAILQ_FOREACH_SAFE
/* rewrite of OpenBSD 6.9 sys/queue.h for linux builds */
#define TAILQ_FOREACH_SAFE(var, head, field, tmp)			\
	for ((var) = ((head)->tqh_first);				\
		(var) != (NULL) && ((tmp) = TAILQ_NEXT(var, field), 1);	\
		(var) = (tmp))
#endif
#ifndef STAILQ_FOREACH_SAFE
#define STAILQ_FOREACH_SAFE(var, head, field, tmp)			\
	for ((var) = ((head)->stqh_first);				\
		(var) && ((tmp) = STAILQ_NEXT(var, field), 1);		\
		(var) = (tmp))
#endif

/* XXX OpenBSD added STAILQ in 6.9; fallback to SIMPLEQ for prior versions. */
#if defined(__OpenBSD__) && !defined(STAILQ_HEAD)
#define SQ(_do)	CONCAT(SIMPLEQ ## _, _do)
#else
#define SQ(_do)	CONCAT(STAILQ ## _, _do)
#endif  /* __OpenBSD__ */

#ifdef __OpenBSD__
#define HAVE_PROGNAME
extern char *__progname;
#define progname __progname
#elif defined(_GNU_SOURCE)
#define HAVE_PROGNAME
extern char *program_invocation_short_name;
#define progname program_invocation_short_name
#else
static char progname[PATH_MAX];
#endif  /* __OpenBSD__ */

enum date_string {
	ISO8601_DATE_ONLY = 10,  /* YYYY-MM-DD */
	ISO8601_DATE_HHMM = 16,  /* YYYY-MM-DD HH:MM */
	ISO8601_TIMESTAMP = 19   /* YYYY-MM-DD HH:MM:SS */
};

struct fnc_file_artifact {
	fsl_card_F		*fc;
	fsl_uuid_str		 puuid;
	uint64_t		 diffstat;
	fsl_ckout_change_e	 change;
};

struct input {
	void		*data;
	char		*prompt;
	enum input_type	 type;
	int		 flags;
#define SR_CLREOL	(1 << 0)
#define SR_UPDATE	(1 << 1)
#define SR_SLEEP	(1 << 2)
#define SR_RESET	(1 << 3)
#define SR_ALL		(SR_CLREOL | SR_UPDATE | SR_SLEEP | SR_RESET)
	char		 buf[BUFSIZ];
	long		 ret;
};

struct artifact_types {
	char	**values;
	short	  nitems;
};

struct cmd_help {
	const char *sopt;
	const char *lopt;
	const char *arg;
	const char *txt;
};

struct fnc_cmd {
	const char	*name;
	const char	*aliases;
	int		 (*f)(int, char **);
	struct cmd_help	*help;
};

Added include/opt.h.







































































































































































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2023 Mark Jamsek <mark@jamsek.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define GLOBAL_HELP(_)								\
	_( "h", "help", NULL, "Display program help and usage then exit.",	\
	    no_argument ),							\
	_( "R", "repo", "path", "Use the Fossil repository at <path>.",		\
	    required_argument ),						\
	_( "v", "version", NULL, "Display program version number then exit.",	\
	    no_argument ),

#define BLAME_HELP(_)								\
	_( "C", "no-colour", NULL,						\
	    "Disable colourised blame. Toggle at runtime with 'c' if this\n\t"	\
	    "option is not used.",						\
	    no_argument ),							\
	_( "c", "commit", "commit",						\
	    "Blame file as at <commit>. Common symbols are:"			\
	    "\n\t    SHA{1,3} hash"						\
	    "\n\t    SHA{1,3} unique prefix"					\
	    "\n\t    branch"							\
	    "\n\t    tag:TAG"							\
	    "\n\t    root:BRANCH"						\
	    "\n\t    ISO8601 date"						\
	    "\n\t    ISO8601 timestamp"						\
	    "\n\t    {tip,current,prev,next}\n\t"				\
	    "For a complete list of symbols see Fossil's Check-in Names:\n\t"	\
	    "https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki",	\
	    required_argument ),						\
	_( "h", "help", NULL, "Display blame command help and usage.",		\
	    no_argument ),							\
	_( "l", "line", "lineno", "Open annotated file at <lineno>.",		\
	    required_argument ),						\
	_( "n", "limit", "n",							\
	    "Limit blame history to <n> commits or seconds denoted with a\n\t"	\
	    "postfixed 's' (e.g., 30s).",					\
	    required_argument ),						\
	_( "r", "reverse", NULL,						\
	    "Reverse annotate with the first time each line was changed after "	\
	    "\n\tthe specified commit. Requires --commit.",			\
	    no_argument ),

#define BRANCH_HELP(_) \
	_( "C", "no-colour", NULL,						\
	    "Disable colourised branch view. Toggle at runtime with 'c' if "	\
	    "\n\tthis option is not used.",					\
	    no_argument ),							\
	_( "a", "after", "date",						\
	    "Show branches active after <date>, which must be either an\n\t"	\
	    "ISO 8601 extended format complete date (e.g., 2020-10-10) or\n\t"	\
	    "an unambiguous DD/MM/YYYY or MM/DD/YYYY formatted date.",		\
	    required_argument ),						\
	_( "b", "before", "date", "Like -a|--after but active before <date>.",	\
	    required_argument ),						\
	_( "c", "closed", NULL, "Show closed branches only.", no_argument ),	\
	_( "h", "help", NULL, "Display branch command help and usage.",		\
	    no_argument ),							\
	_( "o", "open", NULL, "Show open branches only.", no_argument ),	\
	_( "p", "no-private", NULL, "Do not show private branches.",		\
	    no_argument ),							\
	_( "r", "reverse", NULL, "Reverse the display order of branches.",	\
	    no_argument ),							\
	_( "s", "sort", "order", "Sort branches in <order>:"			\
	    "\n\t    mru   - most recently used"				\
	    "\n\t    state - open/closed state"					\
	    "\n\tBranches are lexicographically sorted by default.",		\
	    required_argument ),

#define CONFIG_HELP(_)								\
	_( "h", "help", NULL, "Display config command help and usage.",		\
	    no_argument ),							\
	_( "l", "ls", NULL, "Display all available options.", no_argument ),	\
	_( "u", "unset", "option", "Unset the named repository option.",	\
	    required_argument ),

#define DIFF_HELP(_)								\
	_( "b", "brief", NULL,							\
	    "Display index and hash lines only. Toggle at runtime with 'b'.",	\
	    no_argument ),							\
	_( "C", "no-colour", NULL,						\
	    "Disable colourised diff. Toggle at runtime with 'c' if this\n\t"	\
	    "option is not used.",						\
	    no_argument ),							\
	_( "D", "min-diffstat", NULL,						\
	    "Show minimal vice histogram diffstat. Toggle at runtime with 'D'.",\
	    no_argument ),							\
	_( "h", "help", NULL, "Display diff command help and usage.",		\
	    no_argument ),							\
	_( "i", "invert", NULL,							\
	    "Invert difference between artifacts. Toggle at runtime with 'i'.",	\
	    no_argument ),							\
	_( "l", "line-numbers", NULL,						\
	    "Show file line numbers. Can be toggled at runtime with 'L'.",	\
	    no_argument ),							\
	_( "o", "no-curses", NULL,						\
	    "Write diff directly to the standard output.",			\
	    no_argument ),							\
	_( "P", "no-prototype", NULL,						\
	    "Do not display function prototypes in hunk header.",		\
	    no_argument ),							\
	_( "q", "quiet", NULL,							\
	    "Do not show added or removed file content. Toggle at runtime\n\t"	\
	    "with 'v'.",							\
	    no_argument ),							\
	_( "s", "sbs", NULL,							\
	    "Show side-by-side formatted diff. Toggle at runtime with 'S'.",	\
	    no_argument ),							\
	_( "W", "whitespace-eol", NULL,						\
	    "Ignore end-of-line whitespace-only changes. Toggle at runtime\n\t"	\
	    "with 'W'.",							\
	    no_argument ),							\
	_( "w", "whitespace", NULL,						\
	    "Ignore whitespace-only changes. Toggle at runtime with 'w'.",	\
	    no_argument ),							\
	_( "x", "context", "n", "Show <n> context lines (0 <= n <= 64).",	\
	    required_argument ),

#define STASH_HELP(_)								\
	_( "C", "no-colour", NULL,						\
	    "Disable colourised stash view. Toggle at runtime with 'c' if\n\t"	\
	    "this option is not used.",						\
	    no_argument ),							\
	_( "h", "help", NULL, "Display stash command help and usage.",		\
	    no_argument ),							\
	_( "P", "no-prototype", NULL,						\
	    "Do not display function prototypes in hunk header.",		\
	    no_argument ),							\
	_( "x", "context", "n", "Show <n> context lines (0 <= n <= 64).",	\
	    required_argument ),

#define TIMELINE_HELP(_)							\
	_( "b", "branch", "branch",						\
	    "Only display commits that reside on the given <branch>.",		\
	    required_argument ),						\
	_( "C", "no-colour", NULL,						\
	    "Disable colourised timeline. Toggle at runtime with 'c'\n\t"	\
	    "if this option is not used.",					\
	    no_argument ),							\
	_( "c", "commit", "commit",						\
	    "Open the timeline from <commit>. Common symbols are:"		\
	    "\n\t    SHA{1,3} hash"						\
	    "\n\t    SHA{1,3} unique prefix"					\
	    "\n\t    branch"							\
	    "\n\t    tag:TAG"							\
	    "\n\t    root:BRANCH"						\
	    "\n\t    ISO8601 date"						\
	    "\n\t    ISO8601 timestamp"						\
	    "\n\t    {tip,current,prev,next}\n\t"				\
	    "For a complete list of symbols see Fossil's Check-in Names:\n\t"	\
	    "https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki",	\
	    required_argument ),						\
	_( "f", "filter", "glob",						\
	    "Load commits with <glob> in the comment, user, or branch field.",	\
	    required_argument ),						\
	_( "h", "help", NULL, "Display timeline command help and usage.",	\
	    no_argument ),							\
	_( "n", "limit", "n", "Load timeline with <n> commits.",		\
	    required_argument ),						\
	_( "T", "tag", "tag", "Only load commits with <tag> T cards.",		\
	    required_argument ),						\
	_( "t", "type", "type", "Only display <type> commits. Valid types are:"	\
	    "\n\t    ci - check-in"						\
	    "\n\t    w  - wiki"							\
	    "\n\t    t  - ticket"						\
	    "\n\t    e  - technote"						\
	    "\n\t    f  - forum post"						\
	    "\n\t    g  - tag artifact"						\
	    "\n\tn.b. This is a repeatable flag (e.g., -t ci -t w).",		\
	    required_argument ),						\
	_( "u", "username", "user", "Display commits authored by <username>.",	\
	    required_argument ),						\
	_( "z", "utc", NULL, "Use UTC (instead of local) time.", no_argument ),

#define TREE_HELP(_)								\
	_( "C", "no-colour", NULL,						\
	    "Disable colourised tree. Toggle at runtime with 'c' if this\n\t"	\
	    "option is not used.",						\
	    no_argument ),							\
	_( "c", "commit", "commit",						\
	    "Display repository tree as at <commit>. Common symbols are:"	\
	    "\n\t    SHA{1,3} hash"						\
	    "\n\t    SHA{1,3} unique prefix"					\
	    "\n\t    branch"							\
	    "\n\t    tag:TAG"							\
	    "\n\t    root:BRANCH"						\
	    "\n\t    ISO8601 date"						\
	    "\n\t    ISO8601 timestamp"						\
	    "\n\t    {tip,current,prev,next}\n\t"				\
	    "For a complete list of symbols see Fossil's Check-in Names:\n\t"	\
	    "https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki",	\
	    required_argument ),						\
	_( "h", "help", NULL, "Display tree command help and usage.",		\
	    no_argument ),

#define GEN_GETOPT_HELP(_)					\
	_(global, -1, GLOBAL_HELP)				\
	_(blame, FNC_VIEW_BLAME, BLAME_HELP)			\
	_(branch, FNC_VIEW_BRANCH, BRANCH_HELP)			\
	_(config, FNC_VIEW_CONFIG, CONFIG_HELP)			\
	_(diff, FNC_VIEW_DIFF, DIFF_HELP)			\
	_(stash, FNC_VIEW_STASH, STASH_HELP)			\
	_(timeline, FNC_VIEW_TIMELINE, TIMELINE_HELP)		\
	_(tree, FNC_VIEW_TREE, TREE_HELP)

#define CMD_HELP_STRUCT_VALUE(s, l, a, t, h) { (s), (l), (a), (t) }

#define GETOPT_OPTION_STRUCT_VALUE(s, l, a, t, h) { (l), (h), NULL, (s[0]) }

#define GEN_CMD_HELP_STRUCT(name, id, options)			\
	struct cmd_help help_##name[] = {			\
		options(CMD_HELP_STRUCT_VALUE)			\
		{ NULL, NULL, NULL, NULL }			\
	};							\
	static const struct option name##_opt[] = {		\
		options(GETOPT_OPTION_STRUCT_VALUE)		\
		{ NULL, 0, NULL, 0 }				\
	};

Deleted include/settings.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104








































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
 * Copyright (c) 2021 Mark Jamsek <mark@jamsek.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define GEN_ENUM_SYM(pfx, id)	pfx##_##id
#define GEN_ENUM(name, pfx, info)				\
	enum name { info(pfx, GEN_ENUM_SYM) };

#define GEN_STR_SYM(pfx, id)	#pfx"_"#id
#define GEN_STR(name, pfx, info)				\
	const char *name[] = { info(pfx, GEN_STR_SYM) };

/*
 * All configurable fnc settings, which can be stored in either the fossil(1)
 * repository (e.g., ./repo.fossil) or shell envvars with `export SETTING=val`.
 */
#define USER_OPTIONS(pfx, _)					\
	_(pfx, START_SETTINGS),					\
	_(pfx, COLOUR_COMMIT),					\
	_(pfx, COLOUR_USER),					\
	_(pfx, COLOUR_DATE),					\
	_(pfx, COLOUR_DIFF_META),				\
	_(pfx, COLOUR_DIFF_MINUS),				\
	_(pfx, COLOUR_DIFF_PLUS),				\
	_(pfx, COLOUR_DIFF_HUNK),				\
	_(pfx, COLOUR_DIFF_TAGS),				\
	_(pfx, COLOUR_DIFF_SBS_EDIT),				\
	_(pfx, COLOUR_TREE_LINK),				\
	_(pfx, COLOUR_TREE_DIR),				\
	_(pfx, COLOUR_TREE_EXEC),				\
	_(pfx, COLOUR_BRANCH_OPEN),				\
	_(pfx, COLOUR_BRANCH_CLOSED),				\
	_(pfx, COLOUR_BRANCH_CURRENT),				\
	_(pfx, COLOUR_BRANCH_PRIVATE),				\
	_(pfx, COLOUR_HL_LINE),					\
	_(pfx, COLOUR_HL_SEARCH),				\
	_(pfx, DIFF_CONTEXT),					\
	_(pfx, DIFF_FLAGS),					\
	_(pfx, VIEW_SPLIT_MODE),				\
	_(pfx, VIEW_SPLIT_WIDTH),				\
	_(pfx, VIEW_SPLIT_HEIGHT),				\
	_(pfx, EOF_SETTINGS)

#define LINE_ATTR_ENUM(pfx, _)					\
	_(pfx, AUTO),						\
	_(pfx, MONO)

#define INPUT_TYPE_ENUM(pfx, _)					\
	_(pfx, ALPHA),						\
	_(pfx, NUMERIC)

#define LINE_TYPE_ENUM(pfx, _)					\
	_(pfx, BLANK),						\
	_(pfx, TIMELINE_HEADER),				\
	_(pfx, TIMELINE_COMMIT),				\
	_(pfx, DIFF_HEADER),					\
	_(pfx, DIFF_ARTIFACT),					\
	_(pfx, DIFF_USER),					\
	_(pfx, DIFF_TAGS),					\
	_(pfx, DIFF_DATE),					\
	_(pfx, DIFF_COMMENT),					\
	_(pfx, DIFF_CHANGESET),					\
	_(pfx, DIFF_INDEX),					\
	_(pfx, DIFF_META),					\
	_(pfx, DIFF_MINUS),					\
	_(pfx, DIFF_PLUS),					\
	_(pfx, DIFF_EDIT),					\
	_(pfx, DIFF_CONTEXT),					\
	_(pfx, DIFF_HUNK),					\
	_(pfx, DIFF_SEPARATOR)

#define VIEW_MODE_ENUM(pfx, _)					\
	_(pfx, NONE),						\
	_(pfx, VERT),						\
	_(pfx, HRZN)

#define STASH_MVMT_ENUM(pfx, _)					\
	_(pfx, NONE),						\
	_(pfx, DOWN),						\
	_(pfx, UP),						\
	_(pfx, UPDOWN)

#define ENUM_INFO(_)						\
	_(fnc_opt_id, FNC, USER_OPTIONS)			\
	_(line_attr, SLINE, LINE_ATTR_ENUM)			\
	_(input_type, INPUT, INPUT_TYPE_ENUM)			\
	_(line_type, LINE, LINE_TYPE_ENUM)			\
	_(view_mode, VIEW_SPLIT, VIEW_MODE_ENUM)		\
	_(stash_mvmt, STASH_MVMT, STASH_MVMT_ENUM)

#define GEN_ENUMS(name, pfx, info) GEN_ENUM(name, pfx, info)
ENUM_INFO(GEN_ENUMS)

Changes to lib/libfossil-config.h.

79
80
81
82
83
84
85
86
87
88



89
90
91
92
93
94
95
79
80
81
82
83
84
85



86
87
88
89
90
91
92
93
94
95







-
-
-
+
+
+







#if !defined(HAVE_STDINT_H)
#  define HAVE_STDINT_H 1
#endif
#endif
/* _WIN32 */


#define FSL_LIB_VERSION_HASH "231fed953330909f8c8db7cf93f31c84b4fc51d5"
#define FSL_LIB_VERSION_TIMESTAMP "2023-04-19 12:46:07.202 UTC"
#define FSL_LIB_CONFIG_TIME "2023-04-20 11:48 GMT"
#define FSL_LIB_VERSION_HASH "72f05d4c41e735ba67b37a71664d2b1a2cbe6e87"
#define FSL_LIB_VERSION_TIMESTAMP "2023-11-23 13:07:37.861 UTC"
#define FSL_LIB_CONFIG_TIME "2023-11-24 06:10 GMT"
#if defined(_MSC_VER)
#define FSL_PLATFORM_OS "windows"
#define FSL_PLATFORM_IS_WINDOWS 1
#define FSL_PLATFORM_IS_UNIX 0
#define FSL_PLATFORM_PLATFORM "windows"
#define FSL_PLATFORM_PATH_SEPARATOR ";"
#define FSL_CHECKOUTDB_NAME "./_FOSSIL_"

Changes to lib/libfossil.c.

985
986
987
988
989
990
991
992


993
994
995
996
997
998
999
985
986
987
988
989
990
991

992
993
994
995
996
997
998
999
1000







-
+
+







  }else{
    /* realloc() */
    return FLCA.f(FLCA.state, mem, n);
  }
#undef FLCA
}

void * fsl_realloc_f_stdalloc(void * state __unused, void * mem, fsl_size_t n){
void * fsl_realloc_f_stdalloc( void * state fsl__unused,
                               void * mem, fsl_size_t n ){
  if(!mem){
    return malloc(n);
  }else if(!n){
    free(mem);
    return NULL;
  }else{
    return realloc(mem, n);
2891
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902
2903
2904
2905
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902
2903
2904
2905
2906







-
+







   It expects varg to be a string value, which it will preceed to
   encode using an URL encoding algothrim (certain characters are
   converted to %XX, where XX is their hex value) and passes the
   encoded string to pf(). It returns the total length of the output
   string.
*/
static int spech_urlencode( fsl_output_f pf, void * pfArg,
                            unsigned int pfLen __unused, void * varg ){
                            unsigned int pfLen fsl__unused, void * varg ){
  char const * str = (char const *) varg;
  int rc = 0;
  char ch = 0;
  char const * hex = "0123456789ABCDEF";
#define xbufsz 10
  char xbuf[xbufsz];
  int slen = 0;
5090
5091
5092
5093
5094
5095
5096
5097

5098
5099
5100
5101
5102
5103
5104
5091
5092
5093
5094
5095
5096
5097

5098
5099
5100
5101
5102
5103
5104
5105







-
+







  rc = fsl_delta_applied_size( pDelta->mem, pDelta->used, &n);
  if(rc){
    if(pErr){
      fsl_error_set(pErr, rc, "fsl_delta_applied_size() failed.");
    }
    return rc;
  }
  assert(n>0);
  assert(n>=0);
  rc = fsl_buffer_resize( &out, n );
  if(0==rc){
    rc = fsl_delta_apply2( orig->mem, orig->used,
                          pDelta->mem, pDelta->used,
                          out.mem, pErr);
    if(0==rc) fsl_buffer_swap(&out, pTarget);
  }
5150
5151
5152
5153
5154
5155
5156
5157

5158
5159
5160
5161
5162
5163
5164
5151
5152
5153
5154
5155
5156
5157

5158
5159
5160
5161
5162
5163
5164
5165







-
+







}


int fsl_output_f_buffer( void * state, void const * src, fsl_size_t n ){
  return fsl_buffer_append((fsl_buffer*)state, src, n);
}

int fsl_finalizer_f_buffer( void * state __unused, void * mem ){
int fsl_finalizer_f_buffer( void * state fsl__unused, void * mem ){
  fsl_buffer * b = (fsl_buffer*)mem;
  fsl_buffer_reserve(b, 0);
  *b = fsl_buffer_empty;
  return 0;
}

int fsl_buffer_strftime(fsl_buffer * const b, char const * format,
5301
5302
5303
5304
5305
5306
5307
5308

5309
5310
5311
5312
5313
5314
5315
5302
5303
5304
5305
5306
5307
5308

5309
5310
5311
5312
5313
5314
5315
5316







-
+







}

fsl_size_t fsl_buffer_seek(fsl_buffer * const b, fsl_int_t offset,
                           fsl_buffer_seek_e  whence){
  int64_t c = (int64_t)b->cursor;
  switch(whence){
    case FSL_BUFFER_SEEK_SET: c = offset;
    __attribute__ ((fallthrough));
      FSL_SWITCH_FALL_THROUGH;
    case FSL_BUFFER_SEEK_CUR: c = (int64_t)b->cursor + offset; break;
    case FSL_BUFFER_SEEK_END:
      c = (int64_t)b->used + offset;
      /* ^^^^^ fossil(1) uses (used + offset - 1) but

         That seems somewhat arguable because (used + 0 - 1) is at the
         last-written byte (or 1 before the begining), not the
10719
10720
10721
10722
10723
10724
10725
10726


10727
10728
10729
10730
10731
10732
10733
10720
10721
10722
10723
10724
10725
10726

10727
10728
10729
10730
10731
10732
10733
10734
10735







-
+
+







    We copy fsl_lib_configurable.allocator as a base allocator.
 */
static fsl_allocator fslAllocOrig;

/**
    Proxies fslAllocOrig.f() and abort()s on OOM conditions.
*/
static void * fsl_realloc_f_failing(void * state __unused, void * mem, fsl_size_t n){
static void * fsl_realloc_f_failing(void * state fsl__unused,
                                    void * mem, fsl_size_t n){
  void * rv = fslAllocOrig.f(fslAllocOrig.state, mem, n);
  if(n && !rv){
    fsl__fatal(FSL_RC_OOM, NULL)/*does not return*/;
  }
  return rv;
}

18727
18728
18729
18730
18731
18732
18733
18734


18735
18736
18737
18738
18739


18740
18741
18742
18743
18744


18745
18746
18747
18748
18749
18750
18751
18729
18730
18731
18732
18733
18734
18735

18736
18737
18738
18739
18740
18741

18742
18743
18744
18745
18746
18747

18748
18749
18750
18751
18752
18753
18754
18755
18756







-
+
+




-
+
+




-
+
+







  }
}

/**
    fsl_list_visitor_f() impl which requires that obj be-a (fsl_card_T*),
    which this function passes to fsl_card_T_free().
*/
static int fsl_list_v_card_T_free(void * obj, void * visitorState __unused){
static int fsl_list_v_card_T_free(void * obj,
                                  void * visitorState fsl__unused){
  if(obj) fsl_card_T_free( (fsl_card_T*)obj );
  return 0;
}

static int fsl_list_v_card_Q_free(void * obj, void * visitorState __unused ){
static int fsl_list_v_card_Q_free(void * obj,
                                  void * visitorState fsl__unused){
  if(obj) fsl_card_Q_free( (fsl_card_Q*)obj );
  return 0;
}

static int fsl_list_v_card_J_free(void * obj, void * visitorState __unused){
static int fsl_list_v_card_J_free(void * obj,
                                  void * visitorState fsl__unused){
  if(obj) fsl_card_J_free( (fsl_card_J*)obj );
  return 0;
}

fsl_deck * fsl_deck_malloc(void){
  fsl_deck * rc = (fsl_deck *)fsl_malloc(sizeof(fsl_deck));
  if(rc){
22012
22013
22014
22015
22016
22017
22018
22019


22020
22021
22022
22023
22024
22025
22026
22017
22018
22019
22020
22021
22022
22023

22024
22025
22026
22027
22028
22029
22030
22031
22032







-
+
+







  return rc;
}

/**
   Overrideable crosslink listener which updates the timeline for
   attachment records.
*/
static int fsl_deck_xlink_f_attachment(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_attachment(fsl_deck * const d,
                                       void * state fsl__unused){
  if(FSL_SATYPE_ATTACHMENT!=d->type) return 0;
  int rc;
  fsl_db * const db = fsl_cx_db_repo(d->f);
  fsl_buffer * const comment = fsl__cx_scratchpad(d->f);
  const bool isAdd = (d->A.src && *d->A.src) ? 1 : 0;
  char attachToType = 'w'
    /* Assume wiki until we know otherwise, keeping in mind that the
22090
22091
22092
22093
22094
22095
22096
22097


22098
22099
22100
22101
22102
22103
22104
22096
22097
22098
22099
22100
22101
22102

22103
22104
22105
22106
22107
22108
22109
22110
22111







-
+
+







  return rc;
}

/**
   Overrideable crosslink listener which updates the timeline for
   checkin records.
*/
static int fsl_deck_xlink_f_checkin(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_checkin(fsl_deck * const d,
                                    void * state fsl__unused){
  if(FSL_SATYPE_CHECKIN!=d->type) return 0;
  int rc;
  fsl_db * db;
  db = fsl_cx_db_repo(d->f);
  assert(db);
  rc = fsl_db_exec(db,
       "REPLACE INTO event(type,mtime,objid,user,comment,"
22138
22139
22140
22141
22142
22143
22144
22145


22146
22147
22148
22149
22150
22151
22152
22145
22146
22147
22148
22149
22150
22151

22152
22153
22154
22155
22156
22157
22158
22159
22160







-
+
+







       (int)FSL_TAGID_BGCOLOR, d->rid,
       (int)FSL_TAGID_USER, d->rid,
       (int)FSL_TAGID_COMMENT, d->rid, d->D
  );
  return fsl_cx_uplift_db_error2(d->f, db, rc);
}

static int fsl_deck_xlink_f_control(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_control(fsl_deck * const d,
                                    void * state fsl__unused){
  if(FSL_SATYPE_CONTROL!=d->type) return 0;
  /*
    Create timeline event entry for all tags in this control
    construct. Note that we are using a lot of historical code which
    hard-codes english-lanuage text and links which only work in
    fossil(1). i would prefer to farm this out to a crosslink
    callback, and provide a default implementation which more or
22285
22286
22287
22288
22289
22290
22291
22292


22293
22294
22295
22296
22297
22298
22299
22293
22294
22295
22296
22297
22298
22299

22300
22301
22302
22303
22304
22305
22306
22307
22308







-
+
+








  end:
  fsl__cx_scratchpad_yield(d->f, comment);
  return rc;

}

static int fsl_deck_xlink_f_forum(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_forum(fsl_deck * const d,
                                  void * state fsl__unused){
  if(FSL_SATYPE_FORUMPOST!=d->type) return 0;
  int rc = 0;
  fsl_db * const db = fsl_cx_db_repo(d->f);
  assert(db);
  fsl_cx * const f = d->f;
  fsl_id_t const froot = d->G ? fsl_uuid_to_rid(f, d->G) : d->rid;
  fsl_id_t const fprev = d->P.used ? fsl_uuid_to_rid(f, (char const *)d->P.list[0]): 0;
22371
22372
22373
22374
22375
22376
22377
22378


22379
22380
22381
22382
22383
22384
22385
22380
22381
22382
22383
22384
22385
22386

22387
22388
22389
22390
22391
22392
22393
22394
22395







-
+
+







  dberr:
  assert(rc);
  assert(db->error.code);
  return fsl_cx_uplift_db_error(f, db);
}


static int fsl_deck_xlink_f_technote(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_technote(fsl_deck * const d,
                                     void * state fsl__unused){
  if(FSL_SATYPE_TECHNOTE!=d->type) return 0;
  char buf[FSL_STRLEN_K256 + 7 /* event-UUID\0 */] = {0};
  fsl_id_t tagid;
  char const * zTag;
  int rc = 0;
  fsl_cx * const f = d->f;
  fsl_db * const db = fsl_cx_db_repo(d->f);
22420
22421
22422
22423
22424
22425
22426
22427


22428
22429
22430
22431
22432
22433
22434
22430
22431
22432
22433
22434
22435
22436

22437
22438
22439
22440
22441
22442
22443
22444
22445







-
+
+







                     d->E.julian, d->rid, tagid,
                     d->U, d->C, 
                     (int)FSL_TAGID_BGCOLOR, d->rid);
  }
  return rc;
}

static int fsl_deck_xlink_f_wiki(fsl_deck * const d, void * state __unused){
static int fsl_deck_xlink_f_wiki(fsl_deck * const d,
                                 void * state fsl__unused){
  if(FSL_SATYPE_WIKI!=d->type) return 0;
  int rc;
  char const * zWiki;
  fsl_size_t nWiki = 0;
  char cPrefix = 0;
  char * zTag = fsl_mprintf("wiki-%s", d->L);
  if(!zTag) return FSL_RC_OOM;
24819
24820
24821
24822
24823
24824
24825
24826

24827
24828

24829
24830

24831
24832
24833
24834
24835
24836
24837
24830
24831
24832
24833
24834
24835
24836

24837
24838

24839
24840

24841
24842
24843
24844
24845
24846
24847
24848







-
+

-
+

-
+







    sum3 += z[3];
    z += 4;
    N -= 4;
  }
  sum3 += (sum2 << 8) + (sum1 << 16) + (sum0 << 24);
  switch(N){
    case 3:   sum3 += (z[2] << 8);
      __attribute__ ((fallthrough));
      FSL_SWITCH_FALL_THROUGH;
    case 2:   sum3 += (z[1] << 16);
      __attribute__ ((fallthrough));
      FSL_SWITCH_FALL_THROUGH;
    case 1:   sum3 += (z[0] << 24);
      __attribute__ ((fallthrough));
      FSL_SWITCH_FALL_THROUGH;
    default:  ;
  }
  return sum3;
}

int fsl_delta_create2( unsigned char const *zSrc, fsl_size_t lenSrc,
                       unsigned char const *zOut, fsl_size_t lenOut,
26172
26173
26174
26175
26176
26177
26178
26179

26180
26181
26182
26183
26184
26185
26186
26183
26184
26185
26186
26187
26188
26189

26190
26191
26192
26193
26194
26195
26196
26197







-
+







  BR_CLOSE; RC;
  rc = fdb__out(b, "\n", 1);
  end:
#undef RC
  return rc;
}

static int fdb__tcl_finish(fsl_dibu * const b __unused){
static int fdb__tcl_finish(fsl_dibu * const b fsl__unused){
  int rc = 0;
#if 0
  BR_CLOSE;
  if(0==rc && FSL_DIBU_TCL_BRACES & b->implFlags){
    rc = fdb__out(b, "\n", 1);
  }
#endif
27981
27982
27983
27984
27985
27986
27987
27988

27989
27990
27991
27992
27993
27994
27995
27992
27993
27994
27995
27996
27997
27998

27999
28000
28001
28002
28003
28004
28005
28006







-
+







    *pNResult = nLeft;
    *pResult = aM;
    return 0;
  }

  /* For large alignments, try to use alternative algorithms that are
  ** faster than the O(N*N) Wagner edit distance. */
  if( nLeft*nRight>DIFF_ALIGN_MX
  if( (int64_t)nLeft*(int64_t)nRight>DIFF_ALIGN_MX
      && (pOpt->diffFlags & FSL_DIFF2_SLOW_SBS)==0 ){
    if( (pOpt->diffFlags & FSL_DIFF2_IGNORE_ALLWS)==0 ){
      *pResult = NULL;
      rc = diffBlockAlignmentIgnoreSpace(aLeft, nLeft,aRight,nRight,
                                         pOpt, pResult, pNResult);
      if(rc || *pResult) return rc;
    }
28943
28944
28945
28946
28947
28948
28949
28950
28951


28952
28953

28954
28955
28956
28957
28958
28959
28960
28954
28955
28956
28957
28958
28959
28960


28961
28962
28963

28964
28965
28966
28967
28968
28969
28970
28971







-
-
+
+

-
+








/*
 * Connect to or create a foci virtual table.
 */
static int fociConnect(
  sqlite3 *db,
  void *pAux /*a (fsl_cx*) */,
  int argc __unused,
  const char * const * argv __unused,
  int argc fsl__unused,
  const char * const * argv fsl__unused,
  sqlite3_vtab **ppVtab,
  char **pzErr __unused
  char **pzErr fsl__unused
){
  FociTable *pTab;
  int rc = SQLITE_OK;

  pTab = (FociTable *)sqlite3_malloc(sizeof(FociTable));
  if( !pTab ){
    return SQLITE_NOMEM;
28979
28980
28981
28982
28983
28984
28985
28986




28987
28988
28989
28990
28991
28992
28993
28990
28991
28992
28993
28994
28995
28996

28997
28998
28999
29000
29001
29002
29003
29004
29005
29006
29007







-
+
+
+
+







/*
 * Available scan methods:
 *
 *   (0)     A full scan.  Visit every manifest in the repo.  (Slow)
 *   (1)     checkinID=?.  visit only the single manifest specified.
 *   (2)     symName=?     visit only the single manifest specified.
 */
static int fociBestIndex(sqlite3_vtab *tab __unused, sqlite3_index_info *pIdxInfo){
static int fociBestIndex(
  sqlite3_vtab *tab fsl__unused,
  sqlite3_index_info *pIdxInfo
){
  int i;
  pIdxInfo->estimatedCost = 1000000000.0;
  for( i=0; i<pIdxInfo->nConstraint; i++ ){
    if( !pIdxInfo->aConstraint[i].usable ) continue;
    if( pIdxInfo->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ
     && (pIdxInfo->aConstraint[i].iColumn==FOCI_CHECKINID
            || pIdxInfo->aConstraint[i].iColumn==FOCI_SYMNAME)
29052
29053
29054
29055
29056
29057
29058
29059
29060


29061
29062
29063
29064
29065
29066
29067
29066
29067
29068
29069
29070
29071
29072


29073
29074
29075
29076
29077
29078
29079
29080
29081







-
-
+
+







static int fociEof(sqlite3_vtab_cursor *pCursor){
  FociCursor *pCsr = (FociCursor *)pCursor;
  return pCsr->cf==0;
}

static int fociFilter(
  sqlite3_vtab_cursor *pCursor,
  int idxNum, const char *idxStr __unused,
  int argc __unused, sqlite3_value **argv
  int idxNum, const char *idxStr fsl__unused,
  int argc fsl__unused, sqlite3_value **argv
){
  int rc = SQLITE_OK;
  FociCursor *const pCur = (FociCursor *)pCursor;
  fsl_cx * const f = ((FociTable*)pCur->base.pVtab)->f;

  fsl_deck_finalize(&pCur->d);
  if( idxNum ){
31058
31059
31060
31061
31062
31063
31064
31065

31066
31067
31068
31069
31070
31071
31072
31072
31073
31074
31075
31076
31077
31078

31079
31080
31081
31082
31083
31084
31085
31086







-
+







  FILE * f = (FILE*) state;
  *n = (fsl_size_t)fread( dest, 1, *n, f );
  return *n
    ? 0
    : (feof(f) ? 0 : FSL_RC_IO);
}

void fsl_finalizer_f_FILE( void * state __unused, void * mem ){
void fsl_finalizer_f_FILE( void * state fsl__unused, void * mem ){
  if(mem){
    fsl_fclose((FILE*)mem);
  }
}

int fsl_stream( fsl_input_f inF, void * inState,
                fsl_output_f outF, void * outState ){
31542
31543
31544
31545
31546
31547
31548
31549

31550
31551
31552
31553
31554
31555
31556
31556
31557
31558
31559
31560
31561
31562

31563
31564
31565
31566
31567
31568
31569
31570







-
+







    if(rc) return rc;
  }
  self->list[self->used++] = cp;
  if(self->used<self->capacity) self->list[self->used]=NULL;
  return 0;
}

int fsl_list_v_fsl_free(void * obj, void * visitorState __unused){
int fsl_list_v_fsl_free(void * obj, void * visitorState fsl__unused){
  if(obj) fsl_free( obj );
  return 0;
}

int fsl_list_clear( fsl_list * const self, fsl_list_visitor_f childFinalizer,
                    void * finalizerState ){
  /*
32317
32318
32319
32320
32321
32322
32323
32324

32325
32326
32327
32328
32329
32330
32331
32331
32332
32333
32334
32335
32336
32337

32338
32339
32340
32341
32342
32343
32344
32345







-
+







    rc = fsl_cx_exec(f,
      "INSERT INTO " FSL__TABLE_PIVOT "(rid, mtime, pending, src)"
      "  SELECT %" FSL_ID_T_PFMT ", mtime, 1, 1 "
      "  FROM event WHERE objid=%" FSL_ID_T_PFMT
      " AND type='ci' LIMIT 1",
      rid, rid );
  }
  return rc;  
  return rc;
}

/**
   Set a secondary file of a merge. The primary file must be set
   first. There must be at least one secondary but there can be more
   than one if desired.

33056
33057
33058
33059
33060
33061
33062

33063
33064
33065
33066
33067
33068
33069
33070
33071
33072
33073
33074
33075
33076
33077
33078
33079
33080
33081
33082
33083
33084
33085
33086
33087
33088
33089
33090
33091
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103
33104
33105


33106
33107
33108
33109
33110
33111
33112
33070
33071
33072
33073
33074
33075
33076
33077
33078
33079
33080
33081
33082
33083
33084
33085
33086
33087

































33088
33089
33090
33091
33092
33093
33094
33095
33096







+










-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+







    MARKER(("Contents of [vmerge]:\n"));
    fsl_db_each(db, fsl_stmt_each_f_dump, NULL,
                "SELECT * FROM vmerge order by merge");
  }
  mState.f = f;
  mState.opt = opt;
#define MCB(FCT,RMI,FN) \
  assert(opt->callback); \
  mState.fileChangeType = FCT; \
  mState.fileRmInfo = RMI; \
  mState.filename = FN; \
  rc = opt->callback(&mState); \
  mState.priorName = NULL
#define MCB2(FCT,FN) MCB(FCT,FSL_CKUP_RM_NOT,FN)
  /************************************************************************
  ** All of the information needed to do the merge is now contained in the
  ** FV table.  Starting here, we begin to actually carry out the merge.
  **
  ** First, find files in M and V but not in P and report conflicts.
  ** The file in M will be ignored.  It will be treated as if it
  ** does not exist.
  */
  rc = fsl_cx_prepare(f, &q, "SELECT idm FROM " FSL__TABLE_FVM
                      " WHERE idp=0 AND idv>0 AND idm>0");
  if(rc) goto end;
  while( 0==rc && FSL_RC_STEP_ROW==(rc = fsl_stmt_step(&q)) ){
    fsl_id_t const idm = fsl_stmt_g_id(&q, 0);
    rc = fsl_cx_exec(f, "UPDATE " FSL__TABLE_FVM
                     " SET idm=0 WHERE idm=%" FSL_ID_T_PFMT, idm);
    if(0==rc && opt->callback){
      fsl_buffer * const bName = fsl__cx_scratchpad(f);
      rc = fsl_db_get_buffer(db, bName, false,
                             "SELECT pathname FROM vfile WHERE id=%" FSL_ID_T_PFMT,
                             idm);
      if(0==rc){
        MCB2(FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR,
             fsl_buffer_cstr(bName));
      }
      fsl__cx_scratchpad_yield(f, bName);
    }
  }
  fsl_stmt_finalize(&q);
  switch(rc){
    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
    default: goto end;
  }

  /*
  ** Find files that have changed from P->M but not P->V.
  ** Copy the M content over into V.
  ** First, find files that have changed from P->M but not P->V.  Copy
  ** the M content over into V.
  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT idv, ridm, fn, islinkm FROM " FSL__TABLE_FVM
    " WHERE idp>0 AND idv>0 AND idm>0"
    "   AND ridm!=ridp AND ridv=ridp AND NOT chnged"
  );
  if(rc) goto end;
33144
33145
33146
33147
33148
33149
33150










33151
33152
33153
33154
33155
33156



33157
33158
33159
33160
33161
33162
33163
33128
33129
33130
33131
33132
33133
33134
33135
33136
33137
33138
33139
33140
33141
33142
33143
33144
33145
33146
33147
33148
33149

33150
33151
33152
33153
33154
33155
33156
33157
33158
33159







+
+
+
+
+
+
+
+
+
+





-
+
+
+







    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
    default: goto end;
  }

  /*
  ** Do a three-way merge on files that have changes on both P->M and P->V.
  **
  ** Proceed even if the file doesn't exist on P, as if the common
  ** ancestor of M and V is an empty file. In this case, merge
  ** conflict marks will be added to the file and the user will be
  ** forced to handle them like any other conflict. The alternative is
  ** that we warn the user via opt->callback and let them decide on
  ** whether to keep the copy from P->V (historical default behavior)
  ** or error out.  As of 2023-04, fossil treats this as a normal
  ** merge conflict with an empty common ancestor version, so we'll do
  ** the same.
  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT ridm, idv, ridp, ridv,"
    " FSL_GLOB('binary-glob'," FSL__TABLE_FVM ".fn),"
    " fn, isexe, islinkv, islinkm FROM " FSL__TABLE_FVM
    " WHERE idp>0 AND idv>0 AND idm>0"
    " WHERE /*idp>0 AND*/ idv>0 AND idm>0"
    /* -----^^^^^^^^^^^^^ https://fossil-scm.org/home/info/7c75e47b3c130ff1
       With that clause, entries with no common ancestor are filtered out. */
    "   AND ridm!=ridp AND (ridv!=ridp OR chnged)"
  );
  if(0==rc){
    rc = fsl_buffer_append( absPath, f->ckout.dir, (fsl_int_t)f->ckout.dirLen);
  }
  while( 0==rc && (FSL_RC_STEP_ROW==fsl_stmt_step(&q)) ){
    fsl_id_t const ridm = fsl_stmt_g_id(&q, 0);
33198
33199
33200
33201
33202
33203
33204
33205

33206
33207
33208
33209
33210
33211
33212
33194
33195
33196
33197
33198
33199
33200

33201
33202
33203
33204
33205
33206
33207
33208







-
+







      if(opt->debug){
        MARKER(("Merge: %s\n", zName));
      }
      absPath->used = f->ckout.dirLen;
      rc = fsl_buffer_append(absPath, zName, (fsl_int_t)nName);
      if(rc) break;
      zFullPath = fsl_buffer_cstr(absPath);
      rc = fsl_content_get(f, ridp, &p);
      if(ridp) rc = fsl_content_get(f, ridp, &p);
      if(0==rc) rc = fsl_content_get(f, ridm, &m);
      if(0==rc){
        //unsigned mergeFlags = dryRunFlag ? MERGE_DRYRUN : 0;
        //if(keepMergeFlag!=0) mergeFlags |= MERGE_KEEP_FILES;
        //rc = merge_3way(&p, zFullPath, &m, &r, mergeFlags);
        unsigned int nConflict = 0;
        fsl_buffer * const contentLocal = fsl__cx_content_buffer(f);
33427
33428
33429
33430
33431
33432
33433



33434
33435
33436
33437
33438
33439
33440
33441
33442
33443
33444
33445
33446
33447
33448
33449
33450
33451
33452
33453
33454
33455
33456
33457
33458
33459
33460
33461
33462
33463
33464
33465
33466
33467


33468
33469
33470
33471
33472
33473
33474
33423
33424
33425
33426
33427
33428
33429
33430
33431
33432
33433
33434
33435
33436
33437
33438
33439
33440
33441
33442
33443
33444
33445
33446

33447
33448
33449
33450
33451
33452
33453
33454
33455
33456
33457
33458
33459
33460
33461
33462
33463
33464
33465
33466
33467
33468
33469
33470
33471
33472
33473
33474







+
+
+














-



















+
+







    "SELECT idm, fnm FROM " FSL__TABLE_FVM
    " WHERE idp=0 AND idv=0 AND idm>0"
  );
  while( 0==rc && FSL_RC_STEP_ROW==(rc=fsl_stmt_step(&q)) ){
    fsl_id_t const idm = fsl_stmt_g_id(&q, 0);
    const char *zName;
    fsl_buffer * const bFullName = fsl__cx_scratchpad(f);
    fsl_merge_fchange_e fchange = FSL_MERGE_FCHANGE_NONE
      /* this initialization is bogus, but some gcc versions
         incorrectly report that it may be used uninitialized */;
    rc = fsl_cx_exec(f,
      "REPLACE INTO vfile(vid,chnged,deleted,rid,mrid,"
                         "isexe,islink,pathname,mhash)"
      "  SELECT %" FSL_ID_T_PFMT ",%d,0,rid,mrid,isexe,islink,pathname,"
            "CASE WHEN rid<>mrid"
            " THEN (SELECT uuid FROM blob WHERE blob.rid=vfile.mrid) END "
            "FROM vfile WHERE id=%" FSL_ID_T_PFMT,
      vid, doIntegrate
           ? FSL_VFILE_CHANGE_INTEGRATE_MOD
           : FSL_VFILE_CHANGE_MERGE_ADD,
      idm);
    if(0==rc) rc = fsl_stmt_get_text(&q, 1, &zName, NULL);
    if(0==rc) rc = fsl_buffer_appendf(bFullName, "%s%s", f->ckout.dir, zName);
    if(rc) goto merge_add_end;
    fsl_merge_fchange_e fchange;
    if( fsl_is_file_or_link(fsl_buffer_cstr(bFullName))
        && !fsl_db_exists(db, "SELECT 1 FROM fv WHERE fn=%Q", zName) ){
      if(opt->debug){
        MARKER(("ADDED %s (overwrites an unmanaged file)\n", zName));
      }
      fchange = FSL_MERGE_FCHANGE_CONFLICT_ADDED_UNMANAGED;
    }else{
      if(opt->debug){
        MARKER(("ADDED %s\n", zName));
      }
      fchange = FSL_MERGE_FCHANGE_ADDED;
    }
    if( !opt->dryRun ){
      //undo_save(zName);
      rc = fsl__vfile_to_ckout(f, idm, NULL);
    }
    merge_add_end:
    fsl__cx_scratchpad_yield(f, bFullName);
    if(0==rc && opt->callback){
      assert(FSL_MERGE_FCHANGE_CONFLICT_ADDED_UNMANAGED==fchange
             || FSL_MERGE_FCHANGE_ADDED==fchange);
      MCB2(fchange,zName);
    }
  }
  fsl_stmt_finalize(&q);
  switch(rc){
    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
35029
35030
35031
35032
35033
35034
35035
35036

35037
35038
35039
35040
35041
35042
35043
35029
35030
35031
35032
35033
35034
35035

35036
35037
35038
35039
35040
35041
35042
35043







-
+







    case FSL_RC_STEP_ROW:
      rc = 0;
      *rv = fsl_stmt_g_id(q, 0);
      break;
    case 0:
      rc = 0;
      *rv = 0;
      __attribute__ ((fallthrough));
      FSL_SWITCH_FALL_THROUGH;
    default:
      fsl_cx_uplift_db_error(f, q->db);
      break;
  }
  fsl_stmt_reset(q);
  return rc;
}
41349
41350
41351
41352
41353
41354
41355
41356
41357


41358
41359
41360
41361
41362
41363
41364
41365
41366
41367
41368


41369
41370
41371
41372
41373
41374
41375
41349
41350
41351
41352
41353
41354
41355


41356
41357
41358
41359
41360
41361
41362
41363
41364
41365
41366


41367
41368
41369
41370
41371
41372
41373
41374
41375







-
-
+
+









-
-
+
+








/**
   SQL function to return the number of seconds since 1970.  This is
   the same as strftime('%s','now') but is more compact.
*/
static void fsl_db_now_udf(
  sqlite3_context *context,
  int argc __unused,
  sqlite3_value **argv __unused
  int argc fsl__unused,
  sqlite3_value **argv fsl__unused
){
  sqlite3_result_int64(context, (sqlite3_int64)time(0));
}

/**
   SQL function to convert a Julian Day to a Unix timestamp.
*/
static void fsl_db_j2u_udf(
  sqlite3_context *context,
  int argc __unused,
  sqlite3_value **argv __unused
  int argc fsl__unused,
  sqlite3_value **argv fsl__unused
){
  double const jd = (double)sqlite3_value_double(argv[0]);
  sqlite3_result_int64(context, (sqlite3_int64)fsl_julian_to_unix(jd));
}

/**
   SQL function FSL_CKOUT_DIR([bool includeTrailingSlash=1]) returns
41574
41575
41576
41577
41578
41579
41580
41581
41582


41583
41584
41585
41586
41587
41588
41589
41574
41575
41576
41577
41578
41579
41580


41581
41582
41583
41584
41585
41586
41587
41588
41589







-
-
+
+








/*
   Implement the user() SQL function.  user() takes no arguments and
   returns the user ID of the current user.
*/
static void fsl_db_user_udf(
  sqlite3_context *context,
  int argc __unused,
  sqlite3_value **argv __unused
  int argc fsl__unused,
  sqlite3_value **argv fsl__unused
){
  fsl_cx * f = (fsl_cx*)sqlite3_user_data(context);
  assert(f);
  if(f->repo.user){
    sqlite3_result_text(context, f->repo.user, -1, SQLITE_STATIC);
  }else{
    sqlite3_result_null(context);

Changes to lib/libfossil.h.

250
251
252
253
254
255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276


277
278
279
280
281
282
283
250
251
252
253
254
255
256

257


258
259
260
261
262
263
264
265
266
267
268
269
270
271
272


273
274
275
276
277
278
279
280
281







-
+
-
-















-
-
+
+







#if !defined(FSL_SWITCH_FALL_THROUGH)
#  if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 7)
/*
  #define FSL_USING_GCC

  gcc v7+ treats implicit 'switch' fallthrough as a warning
  (i.e. error because we always build with -Wall -Werror -Wextra
  -pedantic). Because now it's apparently considered modern to warn
  -pedantic).
  for using perfectly valid features of the language. Holy cow, guys,
  what the hell were you thinking!?!?!?

  Similarly braindead, clang #defines __GNUC__.

  _Sigh_.
*/
#    define FSL_SWITCH_FALL_THROUGH __attribute__ ((fallthrough))
#  else
#    define FSL_SWITCH_FALL_THROUGH
#  endif
#endif
/* /FSL_SWITCH_FALL_THROUGH

   TODO: add support for the C++ attributes for doing this.
*/

#if !defined(__unused)
#define __unused
#if !defined(fsl__unused)
#define fsl__unused
#endif


#endif
/* ORG_FOSSIL_SCM_FSL_CONFIG_H_INCLUDED */
/* end of file ./include/fossil-scm/config.h */
/* start of file ./include/fossil-scm/util.h */
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
17709
17710
17711
17712
17713
17714
17715
















17716
17717
17718
17719
17720
17721
17722







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







   was skipped over for merge purposes.

   fossil(1) simply skips over, with a warning, binaries during a
   merge, so we do the same (for lack of a better option).
*/
FSL_MERGE_FCHANGE_CONFLICT_BINARY,
/**
   Indicates that the given file cannot be merged because no common
   ancestor can be found for it. This condition is not strictly fatal
   but does indicate a problem with the input data. Merging will
   continue unless the fsl_merge_f() to which this is reported returns
   non-0 to cancel it.  This particular status is reported very early
   in the fsl_ckout_merge() process, before any files have been
   written by the merge, thus the callback can effectively abort the
   merge without side-effects by returning non-0 if this status is
   reported to it. If the fsl_ckout_merge() call has no callback set,
   this case will go silently undiagnosed!

   Potential TODO: add a flag to fsl_merge_opt to tell it to treat any
   of these cases as merge-fatal.
*/
FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR,
/**
   File was renamed in the updated-to version. If a file is both
   modified and renamed, it will be reported twice: once for each type
   of change. The new name is reported via fsl_merge_state::filename
   and the previous name via fsl_merge_state::priorName.
*/
FSL_MERGE_FCHANGE_RENAMED,
/**

Changes to lib/sqlite3.c.

more than 10,000 changes

Changes to lib/sqlite3.h.

142
143
144
145
146
147
148
149
150
151



152
153
154
155
156
157
158
142
143
144
145
146
147
148



149
150
151
152
153
154
155
156
157
158







-
-
-
+
+
+







** been edited in any way since it was last checked in, then the last
** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.42.0"
#define SQLITE_VERSION_NUMBER 3042000
#define SQLITE_SOURCE_ID      "2023-04-18 23:05:34 ba8e4378f21d529a248d2d60b60974fef0d6612dcaaa1f6b7f8a6946fc46b39b"
#define SQLITE_VERSION        "3.45.0"
#define SQLITE_VERSION_NUMBER 3045000
#define SQLITE_SOURCE_ID      "2023-11-18 18:36:26 6f8f4bfe607f1405d313bb88a33490621002f63e8c02c980f4c083630ad3a6d2"

/*
** 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
524
525
526
527
528
529
530

531
532
533
534
535
536
537
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538







+







#define SQLITE_IOERR_VNODE             (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH              (SQLITE_IOERR | (28<<8))
#define SQLITE_IOERR_BEGIN_ATOMIC      (SQLITE_IOERR | (29<<8))
#define SQLITE_IOERR_COMMIT_ATOMIC     (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC   (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA              (SQLITE_IOERR | (32<<8))
#define SQLITE_IOERR_CORRUPTFS         (SQLITE_IOERR | (33<<8))
#define SQLITE_IOERR_IN_PAGE           (SQLITE_IOERR | (34<<8))
#define SQLITE_LOCKED_SHAREDCACHE      (SQLITE_LOCKED |  (1<<8))
#define SQLITE_LOCKED_VTAB             (SQLITE_LOCKED |  (2<<8))
#define SQLITE_BUSY_RECOVERY           (SQLITE_BUSY   |  (1<<8))
#define SQLITE_BUSY_SNAPSHOT           (SQLITE_BUSY   |  (2<<8))
#define SQLITE_BUSY_TIMEOUT            (SQLITE_BUSY   |  (3<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR      (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR          (SQLITE_CANTOPEN | (2<<8))
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201







-
+







** mode database and there exists at least one client in another process that
** currently has an SQL transaction open on the database. It is set to 0 if
** the database is not a wal-mode db, or if there is no such connection in any
** other process. This opcode cannot be used to detect transactions opened
** by clients within the current process, only within other processes.
**
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use interally by the
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the
** [checksum VFS shim] only.
**
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
** If there is currently no transaction open on the database, and the
** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control
** purges the contents of the in-memory page cache. If there is an open
** transaction, or if the db is a temp-db, this opcode is a no-op, not an error.
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163



















2164
2165
2166


2167
2168
2169
2170
2171
2172
2173
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145



















2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165


2166
2167
2168
2169
2170
2171
2172
2173
2174







-
+















-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+







** to an ORDER BY clause, all fields required by the caller are present in the
** sorted records. However, if SQLite determines based on the declared type
** of a table column that its values are likely to be very large - larger
** than the configured sorter-reference size threshold - then a reference
** is stored in each sorted record and the required column values loaded
** from the database as records are returned in sorted order. The default
** value for this option is to never use this optimization. Specifying a
** negative value for this option restores the default behaviour.
** negative value for this option restores the default behavior.
** This option is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
**
** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
** [sqlite3_int64] parameter which is the default maximum size for an in-memory
** database created using [sqlite3_deserialize()].  This default maximum
** size can be adjusted up or down for individual databases using the
** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control].  If this
** configuration setting is never used, then the default maximum is determined
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option.  If that
** compile-time option is not set, then the default maximum is 1073741824.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD  1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD   2  /* nil */
#define SQLITE_CONFIG_SERIALIZED    3  /* nil */
#define SQLITE_CONFIG_MALLOC        4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC     5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH       6  /* No longer used */
#define SQLITE_CONFIG_PAGECACHE     7  /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP          8  /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS     9  /* boolean */
#define SQLITE_CONFIG_MUTEX        10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX     11  /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE    13  /* int int */
#define SQLITE_CONFIG_PCACHE       14  /* no-op */
#define SQLITE_CONFIG_GETPCACHE    15  /* no-op */
#define SQLITE_CONFIG_LOG          16  /* xFunc, void* */
#define SQLITE_CONFIG_URI          17  /* int */
#define SQLITE_CONFIG_PCACHE2      18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2   19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_SINGLETHREAD         1  /* nil */
#define SQLITE_CONFIG_MULTITHREAD          2  /* nil */
#define SQLITE_CONFIG_SERIALIZED           3  /* nil */
#define SQLITE_CONFIG_MALLOC               4  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC            5  /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_SCRATCH              6  /* No longer used */
#define SQLITE_CONFIG_PAGECACHE            7  /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP                 8  /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS            9  /* boolean */
#define SQLITE_CONFIG_MUTEX               10  /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX            11  /* sqlite3_mutex_methods* */
/* previously SQLITE_CONFIG_CHUNKALLOC    12 which is now unused. */
#define SQLITE_CONFIG_LOOKASIDE           13  /* int int */
#define SQLITE_CONFIG_PCACHE              14  /* no-op */
#define SQLITE_CONFIG_GETPCACHE           15  /* no-op */
#define SQLITE_CONFIG_LOG                 16  /* xFunc, void* */
#define SQLITE_CONFIG_URI                 17  /* int */
#define SQLITE_CONFIG_PCACHE2             18  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2          19  /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20  /* int */
#define SQLITE_CONFIG_SQLLOG       21  /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE    22  /* sqlite3_int64, sqlite3_int64 */
#define SQLITE_CONFIG_SQLLOG              21  /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE           22  /* sqlite3_int64, sqlite3_int64 */
#define SQLITE_CONFIG_WIN32_HEAPSIZE      23  /* int nByte */
#define SQLITE_CONFIG_PCACHE_HDRSZ        24  /* int *psz */
#define SQLITE_CONFIG_PMASZ               25  /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL      26  /* int nByte */
#define SQLITE_CONFIG_SMALL_MALLOC        27  /* boolean */
#define SQLITE_CONFIG_SORTERREF_SIZE      28  /* int nByte */
#define SQLITE_CONFIG_MEMDB_MAXSIZE       29  /* sqlite3_int64 */
2297
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2298
2299
2300
2301
2302
2303
2304

2305
2306
2307
2308
2309
2310
2311
2312







-
+







**
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
** connections at all to the database. If so, it performs a checkpoint
** operation before closing the connection. This option may be used to
** override this behaviour. The first parameter passed to this operation
** override this behavior. The first parameter passed to this operation
** is an integer - positive to disable checkpoints-on-close, or zero (the
** default) to enable them, and negative to leave the setting unchanged.
** The second parameter is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
2447
2448

2449
2450
2451
2452
2453
2454
2455
2456
2457

2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468







2469
2470
2471
2472


2473
2474
2475
2476
2477









2478
2479
2480
2481
2482
2483
2484
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410

2411
2412
2413
2414
2415
2416
2417
2418
2419

2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439

2440
2441
2442
2443
2444
2445
2446
2447
2448

2449
2450
2451
2452
2453
2454
2455
2456
2457

2458
2459
2460
2461

2462
2463
2464
2465
2466
2467
2468

2469
2470
2471
2472
2473
2474
2475
2476
2477


2478
2479
2480
2481



2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497







-
+








-
+








-
+



















-
+








-
+








-
+



-
+






-
+
+
+
+
+
+
+


-
-
+
+


-
-
-
+
+
+
+
+
+
+
+
+







** behaves as it did prior to [version 3.24.0] (2018-06-04).  See the
** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for
** additional information. This feature can also be turned on and off
** using the [PRAGMA legacy_alter_table] statement.
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DML]]
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
** <dt>SQLITE_DBCONFIG_DQS_DML</dt>
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DML statements
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
**
** [[SQLITE_DBCONFIG_DQS_DDL]]
** <dt>SQLITE_DBCONFIG_DQS_DDL</td>
** <dt>SQLITE_DBCONFIG_DQS_DDL</dt>
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
** the legacy [double-quoted string literal] misfeature for DDL statements,
** such as CREATE TABLE and CREATE INDEX. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
**
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</dt>
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
** assume that database schemas are untainted by malicious content.
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
** takes additional defensive steps to protect the application from harm
** including:
** <ul>
** <li> Prohibit the use of SQL functions inside triggers, views,
** CHECK constraints, DEFAULT clauses, expression indexes,
** partial indexes, or generated columns
** unless those functions are tagged with [SQLITE_INNOCUOUS].
** <li> Prohibit the use of virtual tables inside of triggers or views
** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
** </ul>
** This setting defaults to "on" for legacy compatibility, however
** all applications are advised to turn it off if possible. This setting
** can also be controlled using the [PRAGMA trusted_schema] statement.
** </dd>
**
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt>
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
** the legacy file format flag.  When activated, this flag causes all newly
** created database file to have a schema format version number (the 4-byte
** integer found at offset 44 into the database header) of 1.  This in turn
** means that the resulting database file will be readable and writable by
** any SQLite version back to 3.0.0 ([dateof:3.0.0]).  Without this setting,
** newly created databases are generally not understandable by SQLite versions
** prior to 3.3.0 ([dateof:3.3.0]).  As these words are written, there
** is now scarcely any need to generated database files that are compatible
** is now scarcely any need to generate database files that are compatible
** all the way back to version 3.0.0, and so this setting is of little
** practical use, but is provided so that SQLite can continue to claim the
** ability to generate new database files that are compatible with  version
** 3.0.0.
** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
** the [VACUUM] command will fail with an obscure error when attempting to
** process a table with generated columns and a descending index.  This is
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
** either generated columns or decending indexes.
** either generated columns or descending indexes.
** </dd>
**
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</td>
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
** statistics. For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
** by default.</dd>
** by default.  This option takes two arguments: an integer and a pointer to
** an integer..  The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option.  If the second argument
** is not NULL, then the value of the statement scanstatus setting after
** processing the first argument is written into the integer that the second
** argument points to.
** </dd>
**
** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</td>
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option change the default order
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</dt>
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order
** in which tables and indexes are scanned so that the scans start at the end
** and work toward the beginning rather than starting at the beginning and
** working toward the end.  Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
** same as setting [PRAGMA reverse_unordered_selects].  This configuration option
** is useful for application testing.</dd>
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
** same as setting [PRAGMA reverse_unordered_selects].  This option takes
** two arguments which are an integer and a pointer to an integer.  The first
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
** reverse scan order flag, respectively.  If the second argument is not NULL,
** then 0 or 1 is written into the integer that the second argument points to
** depending on if the reverse scan order flag is set after processing the
** first argument.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME            1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE             1001 /* void* int int */
#define SQLITE_DBCONFIG_ENABLE_FKEY           1002 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_TRIGGER        1003 /* int int* */
2492
2493
2494
2495
2496
2497
2498
2499

2500
2501
2502
2503
2504
2505
2506
2505
2506
2507
2508
2509
2510
2511

2512
2513
2514
2515
2516
2517
2518
2519







-
+







#define SQLITE_DBCONFIG_WRITABLE_SCHEMA       1011 /* int int* */
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    1012 /* int int* */
#define SQLITE_DBCONFIG_DQS_DML               1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL               1014 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_VIEW           1015 /* int int* */
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    1016 /* int int* */
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA        1017 /* int int* */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS       1018 /* int int*  */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS       1018 /* int int* */
#define SQLITE_DBCONFIG_REVERSE_SCANORDER     1019 /* int int* */
#define SQLITE_DBCONFIG_MAX                   1019 /* Largest DBCONFIG */

/*
** CAPI3REF: Enable Or Disable Extended Result Codes
** METHOD: sqlite3
**
2719
2720
2721
2722
2723
2724
2725

2726
2727
2728
2729
2730
2731
2732
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746







+







** not effected by the sqlite3_interrupt().
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
**
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
** or not an interrupt is currently in effect for [database connection] D.
** It returns 1 if an interrupt is currently in effect, or 0 otherwise.
*/
SQLITE_API void sqlite3_interrupt(sqlite3*);
SQLITE_API int sqlite3_is_interrupted(sqlite3*);

/*
** CAPI3REF: Determine If An SQL Statement Is Complete
**
3372
3373
3374
3375
3376
3377
3378
3379
3380




3381
3382
3383
3384
3385
3386
3387
3386
3387
3388
3389
3390
3391
3392


3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403







-
-
+
+
+
+







** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback
** function X against [database connection] D, using property mask M
** and context pointer P.  ^If the X callback is
** NULL or if the M mask is zero, then tracing is disabled.  The
** M argument should be the bitwise OR-ed combination of
** zero or more [SQLITE_TRACE] constants.
**
** ^Each call to either sqlite3_trace() or sqlite3_trace_v2() overrides
** (cancels) any prior calls to sqlite3_trace() or sqlite3_trace_v2().
** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P)
** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or
** sqlite3_trace_v2(D,M,X,P) for the [database connection] D.  Each
** database connection may have at most one trace callback.
**
** ^The X callback is invoked whenever any of the events identified by
** mask M occur.  ^The integer return value from the callback is currently
** ignored, though this may change in future releases.  Callback
** implementations should return zero to ensure future compatibility.
**
** ^A trace callback is invoked with four arguments: callback(T,C,P,X).
3742
3743
3744
3745
3746
3747
3748
3749

3750
3751
3752
3753
3754
3755
3756
3758
3759
3760
3761
3762
3763
3764

3765
3766
3767
3768
3769
3770
3771
3772







-
+







** that check if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of that query parameter.
**
** The first parameter to these interfaces (hereafter referred to
** as F) must be one of:
** <ul>
** <li> A database filename pointer created by the SQLite core and
** passed into the xOpen() method of a VFS implemention, or
** passed into the xOpen() method of a VFS implementation, or
** <li> A filename obtained from [sqlite3_db_filename()], or
** <li> A new filename constructed using [sqlite3_create_filename()].
** </ul>
** If the F parameter is not one of the above, then the behavior is
** undefined and probably undesirable.  Older versions of SQLite were
** more tolerant of invalid F parameters than newer versions.
**
3855
3856
3857
3858
3859
3860
3861
3862

3863
3864
3865
3866
3867
3868
3869
3871
3872
3873
3874
3875
3876
3877

3878
3879
3880
3881
3882
3883
3884
3885







-
+







** behavior.
*/
SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);

/*
** CAPI3REF: Create and Destroy VFS Filenames
**
** These interfces are provided for use by [VFS shim] implementations and
** These interfaces are provided for use by [VFS shim] implementations and
** are not useful outside of that context.
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
** with N URI parameters key/values pairs in the array P.  The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
3934
3935
3936
3937
3938
3939
3940
3941



3942
3943
3944
3945
3946
3947
3948



3949
3950
3951
3952
3953
3954
3955
3950
3951
3952
3953
3954
3955
3956

3957
3958
3959
3960
3961
3962
3963
3964


3965
3966
3967
3968
3969
3970
3971
3972
3973
3974







-
+
+
+





-
-
+
+
+







** <li> sqlite3_extended_errcode()
** <li> sqlite3_errmsg()
** <li> sqlite3_errmsg16()
** <li> sqlite3_error_offset()
** </ul>
**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
** text that describes the error, as either UTF-8 or UTF-16 respectively,
** or NULL if no error message is available.
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
** ^(Memory to hold the error message string is managed internally.
** The application does not need to worry about freeing the result.
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr() interface returns the English-language text
** that describes the [result code], as UTF-8.
** ^The sqlite3_errstr(E) interface returns the English-language text
** that describes the [result code] E, as UTF-8, or NULL if E is not an
** result code for which a text error message is available.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token.  ^The byte offset returned by
** sqlite3_error_offset() assumes that the input SQL is UTF8.
4402
4403
4404
4405
4406
4407
4408



































4409
4410
4411
4412
4413
4414
4415
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







** prepared statement S is an EXPLAIN statement, or 2 if the
** statement S is an EXPLAIN QUERY PLAN.
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
** an ordinary statement or a NULL pointer.
*/
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
** setting for [prepared statement] S.  If E is zero, then S becomes
** a normal prepared statement.  If E is 1, then S behaves as if
** its SQL text began with "[EXPLAIN]".  If E is 2, then S behaves as if
** its SQL text began with "[EXPLAIN QUERY PLAN]".
**
** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
** SQLite tries to avoid a reprepare, but a reprepare might be necessary
** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
**
** Because of the potential need to reprepare, a call to
** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
** reprepared because it was created using [sqlite3_prepare()] instead of
** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
** hence has no saved SQL text with which to reprepare.
**
** Changing the explain setting for a prepared statement does not change
** the original SQL text for the statement.  Hence, if the SQL text originally
** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
** is called to convert the statement into an ordinary statement, the EXPLAIN
** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
** output, even though the statement now acts like a normal SQL statement.
**
** This routine returns SQLITE_OK if the explain mode is successfully
** changed, or an error code if the explain mode could not be changed.
** The explain mode cannot be changed while a statement is active.
** Hence, it is good practice to call [sqlite3_reset(S)]
** immediately prior to calling sqlite3_stmt_explain(S,E).
*/
SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);

/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
** [sqlite3_step(S)] but has neither run to completion (returned
4565
4566
4567
4568
4569
4570
4571
4572

4573
4574
4575
4576
4577
4578
4579
4619
4620
4621
4622
4623
4624
4625

4626
4627
4628
4629
4630
4631
4632
4633







-
+







** ^The fifth argument to the BLOB and string binding interfaces controls
** or indicates the lifetime of the object referenced by the third parameter.
** These three options exist:
** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
** with it may be passed. ^It is called to dispose of the BLOB or string even
** if the call to the bind API fails, except the destructor is not called if
** the third parameter is a NULL pointer or the fourth parameter is negative.
** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
** the application remains responsible for disposing of the object. ^In this
** case, the object and the provided pointer to it must remain valid until
** either the prepared statement is finalized or the same SQL parameter is
** bound to something else, whichever occurs sooner.
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
** object and pointer to it must remain valid until then. ^SQLite will then
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254






5255
5256
5257
5258










5259
5260
5261
5262
5263

5264
5265
5266
5267
5268
5269
5270
5298
5299
5300
5301
5302
5303
5304




5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337







-
-
-
-
+
+
+
+
+
+




+
+
+
+
+
+
+
+
+
+





+







** ^Any SQL statement variables that had values bound to them using
** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
** Use [sqlite3_clear_bindings()] to reset the bindings.
**
** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
** back to the beginning of its program.
**
** ^If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
** or if [sqlite3_step(S)] has never before been called on S,
** then [sqlite3_reset(S)] returns [SQLITE_OK].
** ^The return code from [sqlite3_reset(S)] indicates whether or not
** the previous evaluation of prepared statement S completed successfully.
** ^If [sqlite3_step(S)] has never before been called on S or if
** [sqlite3_step(S)] has not been called since the previous call
** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return
** [SQLITE_OK].
**
** ^If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S indicated an error, then
** [sqlite3_reset(S)] returns an appropriate [error code].
** ^The [sqlite3_reset(S)] interface might also return an [error code]
** if there were no prior errors but the process of resetting
** the prepared statement caused a new error. ^For example, if an
** [INSERT] statement with a [RETURNING] clause is only stepped one time,
** that one call to [sqlite3_step(S)] might return SQLITE_ROW but
** the overall statement might still fail and the [sqlite3_reset(S)] call
** might return SQLITE_BUSY if locking constraints prevent the
** database change from committing.  Therefore, it is important that
** applications check the return code from [sqlite3_reset(S)] even if
** no prior call to [sqlite3_step(S)] indicated a problem.
**
** ^The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);


/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
5468
5469
5470
5471
5472
5473
5474
5475

5476
5477
5478
5479
5480
5481
5482
5535
5536
5537
5538
5539
5540
5541

5542
5543
5544
5545
5546
5547
5548
5549







-
+







** schema structures such as [CHECK constraints], [DEFAULT clauses],
** [expression indexes], [partial indexes], or [generated columns].
** <p>
** The SQLITE_DIRECTONLY flag is recommended for any
** [application-defined SQL function]
** that has side-effects or that could potentially leak sensitive information.
** This will prevent attacks in which an application is tricked
** into using a database file that has had its schema surreptiously
** into using a database file that has had its schema surreptitiously
** modified to invoke the application-defined function in ways that are
** harmful.
** <p>
** Some people say it is good practice to set SQLITE_DIRECTONLY on all
** [application-defined SQL functions], regardless of whether or not they
** are security sensitive, as doing so prevents those functions from being used
** inside of the database schema, and thus ensures that the database
5504
5505
5506
5507
5508
5509
5510
5511

5512
5513
5514
5515
5516
5517



















5518
5519
5520
5521
5522
5523
5524

5525
5526
5527
5528
5529
5530
5531
5571
5572
5573
5574
5575
5576
5577

5578
5579





5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613







-
+

-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







+







** are innocuous.  Developers are advised to avoid using the
** SQLITE_INNOCUOUS flag for application-defined functions unless the
** function has been carefully audited and found to be free of potentially
** security-adverse side-effects and information-leaks.
** </dd>
**
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
** functions. However, if it is not specified for a user-defined window
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
** SQL functions that invokes [sqlite3_value_subtype()] should have this
** property.  If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
**
** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>
** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
** result.
** Every function that invokes [sqlite3_result_subtype()] should have this
** property.  If it does not, then the call to [sqlite3_result_subtype()]
** might become a no-op if the function is used as term in an
** [expression index].  On the other hand, SQL functions that never invoke
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
** </dd>
** </dl>
*/
#define SQLITE_DETERMINISTIC    0x000000800
#define SQLITE_DIRECTONLY       0x000080000
#define SQLITE_SUBTYPE          0x000100000
#define SQLITE_INNOCUOUS        0x000200000
#define SQLITE_RESULT_SUBTYPE   0x001000000

/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
** These functions are [deprecated].  In order to maintain
** backwards compatibility with older code, these functions continue
5714
5715
5716
5717
5718
5719
5720






5721
5722
5723
5724
5725
5726
5727
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815







+
+
+
+
+
+







** METHOD: sqlite3_value
**
** The sqlite3_value_subtype(V) function returns the subtype for
** an [application-defined SQL function] argument V.  The subtype
** information can be used to pass a limited amount of context from
** one SQL function to another.  Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
** Every [application-defined SQL function] that invoke this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
** might return zero instead of the upstream subtype in some corner cases.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);

/*
** CAPI3REF: Copy And Free SQL Values
** METHOD: sqlite3_value
**
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824






5825
5826
5827
5828
5829

5830
5831
5832

5833
5834
5835
5836
5837


5838
5839
5840


5841
5842
5843
5844


5845
5846
5847
5848
5849
5850
5851




5852
5853

5854
5855
5856
5857
5858






5859
5860

5861
5862
5863
5864
5865
5866
5867
5868
5869


5870
5871
5872
5873























































5874
5875
5876
5877
5878
5879
5880
5900
5901
5902
5903
5904
5905
5906






5907
5908
5909
5910
5911
5912
5913
5914
5915
5916

5917
5918
5919

5920
5921
5922
5923


5924
5925
5926


5927
5928
5929
5930


5931
5932
5933
5934
5935
5936
5937
5938

5939
5940
5941
5942
5943

5944
5945
5946
5947
5948

5949
5950
5951
5952
5953
5954
5955

5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
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
6025
6026
6027
6028
6029
6030
6031
6032
6033







-
-
-
-
-
-
+
+
+
+
+
+




-
+


-
+



-
-
+
+

-
-
+
+


-
-
+
+






-
+
+
+
+

-
+




-
+
+
+
+
+
+

-
+









+
+




+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);

/*
** CAPI3REF: Function Auxiliary Data
** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
** some circumstances the associated metadata may be preserved.  An example
** of where this might be useful is in a regular-expression matching
** function. The compiled version of the regular expression can be stored as
** metadata associated with the pattern string.
** associate auxiliary data with argument values. If the same argument
** value is passed to multiple invocations of the same SQL function during
** query execution, under some circumstances the associated auxiliary data
** might be preserved.  An example of where this might be useful is in a
** regular-expression matching function. The compiled version of the regular
** expression can be stored as auxiliary data associated with the pattern string.
** Then as long as the pattern string remains the same,
** the compiled regular expression can be reused on multiple
** invocations of the same function.
**
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data
** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
** value to the application-defined function.  ^N is zero for the left-most
** function argument.  ^If there is no metadata
** function argument.  ^If there is no auxiliary data
** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
** returns a NULL pointer.
**
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
** argument of the application-defined function.  ^Subsequent
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
** N-th argument of the application-defined function.  ^Subsequent
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
** NULL if the metadata has been discarded.
** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or
** NULL if the auxiliary data has been discarded.
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
** SQLite will invoke the destructor function X with parameter P exactly
** once, when the metadata is discarded.
** SQLite is free to discard the metadata at any time, including: <ul>
** once, when the auxiliary data is discarded.
** SQLite is free to discard the auxiliary data at any time, including: <ul>
** <li> ^(when the corresponding function parameter changes)^, or
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
**      SQL statement)^, or
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
**       parameter)^, or
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
**      allocation error occurs.)^ </ul>
**      allocation error occurs.)^
** <li> ^(during the original sqlite3_set_auxdata() call if the function
**      is evaluated during query planning instead of during query execution,
**      as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul>
**
** Note the last bullet in particular.  The destructor X in
** Note the last two bullets in particular.  The destructor X in
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
** sqlite3_set_auxdata() interface even returns.  Hence sqlite3_set_auxdata()
** should be called near the end of the function implementation and the
** function implementation should not make any use of P after
** sqlite3_set_auxdata() has been called.
** sqlite3_set_auxdata() has been called.  Furthermore, a call to
** sqlite3_get_auxdata() that occurs immediately after a corresponding call
** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
** condition occurred during the sqlite3_set_auxdata() call or if the
** function is being evaluated during query planning rather than during
** query execution.
**
** ^(In practice, metadata is preserved between function calls for
** ^(In practice, auxiliary data is preserved between function calls for
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
** The value of the N parameter to these interfaces should be non-negative.
** Future enhancements may make use of negative N values to define new
** kinds of function caching behavior.
**
** These routines must be called from the same thread in which
** the SQL function is running.
**
** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()].
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));

/*
** CAPI3REF: Database Connection Client Data
** METHOD: sqlite3
**
** These functions are used to associate one or more named pointers
** with a [database connection].
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
** to be attached to [database connection] D using name N.  Subsequent
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.
**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
** <ul>
** <li> An out-of-memory error occurs during the call to
**      sqlite3_set_clientdata() which attempts to register pointer P.
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
**      with the same D and N parameters.
** <li> The database connection closes.  SQLite does not make any guarantees
**      about the order in which destructors are called, only that all
**      destructors will be called exactly once at some point during the
**      database connection closing process.
** </ul>
**
** SQLite does not do anything with client data other than invoke
** destructors on the client data at the appropriate time.  The intended
** use for client data is to provide a mechanism for wrapper libraries
** to store additional information about an SQLite database connection.
**
** There is no limit (other than available memory) on the number of different
** client data pointers (with different names) that can be attached to a
** single database connection.  However, the implementation is optimized
** for the case of having only one or two different client data names.
** Applications and wrapper libraries are discouraged from using more than
** one client data name each.
**
** There is no way to enumerate the client data pointers
** associated with a database connection.  The N parameter can be thought
** of as a secret key such that only code that knows the secret key is able
** to access the associated data.
**
** Security Warning:  These interfaces should not be exposed in scripting
** languages or in other circumstances where it might be possible for an
** an attacker to invoke them.  Any agent that can invoke these interfaces
** can probably also take control of the process.
**
** Database connection client data is only available for SQLite
** version 3.44.0 ([dateof:3.44.0]) and later.
**
** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].
*/
SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);
SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*));

/*
** CAPI3REF: Constants Defining Special Destructor Behavior
**
** These are special values for the destructor that is passed in as the
** final argument to routines like [sqlite3_result_blob()].  ^If the destructor
** argument is SQLITE_STATIC, it means that the content pointer is constant
6068
6069
6070
6071
6072
6073
6074














6075
6076
6077
6078
6079
6080
6081
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248







+
+
+
+
+
+
+
+
+
+
+
+
+
+







** The sqlite3_result_subtype(C,T) function causes the subtype of
** the result from the [application-defined SQL function] with
** [sqlite3_context] C to be the value T.  Only the lower 8 bits
** of the subtype T are preserved in current versions of SQLite;
** higher order bits are discarded.
** The number of subtype bytes preserved by SQLite might increase
** in future releases of SQLite.
**
** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_RESULT_SUBTYPE] property in its
** text encoding argument when the SQL function is
** [sqlite3_create_function|registered].  If the [SQLITE_RESULT_SUBTYPE]
** property is omitted from the function that invokes sqlite3_result_subtype(),
** then in some cases the sqlite3_result_subtype() might fail to set
** the result subtype.
**
** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
** SQL function that invokes the sqlite3_result_subtype() interface
** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
** an error.  Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
** by default.
*/
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);

/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
**
6239
6240
6241
6242
6243
6244
6245







6246
6247
6248
6249
6250
6251
6252
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426







+
+
+
+
+
+
+







** requested from the operating system is returned.
**
** ^SQLite implements this interface by calling the xSleep()
** method of the default [sqlite3_vfs] object.  If the xSleep() method
** of the default VFS is not implemented correctly, or not implemented at
** all, then the behavior of sqlite3_sleep() may deviate from the description
** in the previous paragraphs.
**
** If a negative argument is passed to sqlite3_sleep() the results vary by
** VFS and operating system.  Some system treat a negative argument as an
** instruction to sleep forever.  Others understand it to mean do not sleep
** at all. ^In SQLite version 3.42.0 and later, a negative
** argument passed into sqlite3_sleep() is changed to zero before it is relayed
** down into the xSleep method of the VFS.
*/
SQLITE_API int sqlite3_sleep(int);

/*
** CAPI3REF: Name Of The Folder Holding Temporary Files
**
** ^(If this global variable is made to point to a string which is
6492
6493
6494
6495
6496
6497
6498
6499

6500
6501
6502
6503
6504
6505
6506
6666
6667
6668
6669
6670
6671
6672

6673
6674
6675
6676
6677
6678
6679
6680







-
+







** </ol>
** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
** a valid schema, then -1 is returned.
*/
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);

/*
** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
** CAPI3REF: Allowed return values from sqlite3_txn_state()
** KEYWORDS: {transaction state}
**
** These constants define the current transaction state of a database file.
** ^The [sqlite3_txn_state(D,S)] interface returns one of these
** constants in order to describe the transaction state of schema S
** in [database connection] D.
**
6624
6625
6626
6627
6628
6629
6630
6631

6632
6633
6634
6635
6636
6637
6638
6798
6799
6800
6801
6802
6803
6804

6805
6806
6807
6808
6809
6810
6811
6812







-
+







** invoked whenever the database connection closes or when the callback
** is overwritten by another invocation of sqlite3_autovacuum_pages().
**
** <p>^There is only one autovacuum pages callback per database connection.
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
** previous invocations for that database connection.  ^If the callback
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
** then the autovacuum steps callback is cancelled.  The return value
** then the autovacuum steps callback is canceled.  The return value
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
** be some other error code if something goes wrong.  The current
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
** return codes might be added in future releases.
**
** <p>If no autovacuum pages callback is specified (the usual case) or
** a NULL pointer is provided for the callback,
7143
7144
7145
7146
7147
7148
7149




7150
7151
7152
7153
7154
7155
7156
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334







+
+
+
+







  ** below are for version 2 and greater. */
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  int (*xRelease)(sqlite3_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
  /* The methods above are in versions 1 and 2 of the sqlite_module object.
  ** Those below are for version 3 and greater. */
  int (*xShadowName)(const char*);
  /* The methods above are in versions 1 through 3 of the sqlite_module object.
  ** Those below are for version 4 and greater. */
  int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
                    const char *zTabName, int mFlags, char **pzErr);
};

/*
** CAPI3REF: Virtual Table Indexing Information
** KEYWORDS: sqlite3_index_info
**
** The sqlite3_index_info structure and its substructures is used as part
7630
7631
7632
7633
7634
7635
7636
7637

7638
7639
7640
7641
7642
7643
7644
7808
7809
7810
7811
7812
7813
7814

7815
7816
7817
7818
7819
7820
7821
7822







-
+







** ^If the blob handle being closed was opened for read-write access, and if
** the database is in auto-commit mode and there are no other open read-write
** blob handles or active write statements, the current transaction is
** committed. ^If an error occurs while committing the transaction, an error
** code is returned and the transaction rolled back.
**
** Calling this function with an argument that is not a NULL pointer or an
** open blob handle results in undefined behaviour. ^Calling this routine
** open blob handle results in undefined behavior. ^Calling this routine
** with a null pointer (such as would be returned by a failed call to
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
** is passed a valid open blob handle, the values returned by the
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
*/
SQLITE_API int sqlite3_blob_close(sqlite3_blob *);

7866
7867
7868
7869
7870
7871
7872
7873
7874
7875



7876
7877
7878
7879
7880
7881
7882
8044
8045
8046
8047
8048
8049
8050



8051
8052
8053
8054
8055
8056
8057
8058
8059
8060







-
-
-
+
+
+







** behavior.)^
**
** ^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 by the
** calling thread or is not currently allocated.
**
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
** sqlite3_mutex_leave() is a NULL pointer, then all three routines
** behave as no-ops.
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,
** then any of the four routines behaves as a no-op.
**
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
8110
8111
8112
8113
8114
8115
8116

8117
8118
8119
8120
8121
8122
8123
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302







+







** Applications should not use any of these parameters or the
** [sqlite3_test_control()] interface.
*/
#define SQLITE_TESTCTRL_FIRST                    5
#define SQLITE_TESTCTRL_PRNG_SAVE                5
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
#define SQLITE_TESTCTRL_PRNG_RESET               7  /* NOT USED */
#define SQLITE_TESTCTRL_FK_NO_ACTION             7
#define SQLITE_TESTCTRL_BITVEC_TEST              8
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
#define SQLITE_TESTCTRL_PENDING_BYTE            11
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14  /* NOT USED */
8138
8139
8140
8141
8142
8143
8144

8145

8146
8147
8148
8149
8150
8151
8152
8317
8318
8319
8320
8321
8322
8323
8324

8325
8326
8327
8328
8329
8330
8331
8332







+
-
+







#define SQLITE_TESTCTRL_RESULT_INTREAL          27
#define SQLITE_TESTCTRL_PRNG_SEED               28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS     29
#define SQLITE_TESTCTRL_SEEK_COUNT              30
#define SQLITE_TESTCTRL_TRACEFLAGS              31
#define SQLITE_TESTCTRL_TUNE                    32
#define SQLITE_TESTCTRL_LOGEST                  33
#define SQLITE_TESTCTRL_USELONGDOUBLE           34
#define SQLITE_TESTCTRL_LAST                    33  /* Largest TESTCTRL */
#define SQLITE_TESTCTRL_LAST                    34  /* Largest TESTCTRL */

/*
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords
** recognized by SQLite.  Applications can uses these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
9594
9595
9596
9597
9598
9599
9600
9601

9602
9603
9604
9605
9606
9607
9608
9774
9775
9776
9777
9778
9779
9780

9781
9782
9783
9784
9785
9786
9787
9788







-
+







** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
** </dd>
**
** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
** prohibits that virtual table from being used from within triggers and
** views.
** </dd>
**
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
9784
9785
9786
9787
9788
9789
9790
9791

9792
9793
9794
9795
9796
9797
9798
9964
9965
9966
9967
9968
9969
9970

9971
9972
9973
9974
9975
9976
9977
9978







-
+







** undefined and probably harmful.
**
** ^(A constraint on a virtual table of the form
** "[IN operator|column IN (...)]" is
** communicated to the xBestIndex method as a
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^  If xBestIndex wants to use
** this constraint, it must set the corresponding
** aConstraintUsage[].argvIndex to a postive integer.  ^(Then, under
** aConstraintUsage[].argvIndex to a positive integer.  ^(Then, under
** the usual mode of handling IN operators, SQLite generates [bytecode]
** that invokes the [xFilter|xFilter() method] once for each value
** on the right-hand side of the IN operator.)^  Thus the virtual table
** only sees a single value from the right-hand side of the IN operator
** at a time.
**
** In some cases, however, it would be advantageous for the virtual
10213
10214
10215
10216
10217
10218
10219
10220

10221
10222
10223
10224
10225
10226
10227
10393
10394
10395
10396
10397
10398
10399

10400
10401
10402
10403
10404
10405
10406
10407







-
+







** operation; or 1 for inserts, updates, or deletes invoked by top-level
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
** When the [sqlite3_blob_write()] API is used to update a blob column,
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
** in this case the new values are not available. In this case, when a
** callback made with op==SQLITE_DELETE is actuall a write using the
** callback made with op==SQLITE_DELETE is actually a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
** pre-update hook is being invoked for some other reason, including a
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
**
** See also:  [sqlite3_update_hook()]
*/
10473
10474
10475
10476
10477
10478
10479







10480
10481
10482
10483
10484
10485
10486
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673







+
+
+
+
+
+
+







** memory representation of the database exists.  A contiguous memory
** representation of the database will usually only exist if there has
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
** values of D and S.
** The size of the database is written into *P even if the
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
** of the database exists.
**
** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,
** the returned buffer content will remain accessible and unchanged
** until either the next write operation on the connection or when
** the connection is closed, and applications must not modify the
** buffer. If the bit had been clear, the returned buffer will not
** be accessed by SQLite after the call.
**
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
10521
10522
10523
10524
10525
10526
10527



10528
10529
10530
10531
10532
10533
10534
10535







10536
10537
10538
10539
10540
10541
10542
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739







+
+
+








+
+
+
+
+
+
+







** size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
** connection closes.  If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
** SQLite will try to increase the buffer size using sqlite3_realloc64()
** if writes on the database cause it to grow larger than M bytes.
**
** Applications must not modify the buffer P or invalidate it before
** the database connection D is closed.
**
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
** database is currently in a read transaction or is involved in a backup
** operation.
**
** It is not possible to deserialized into the TEMP database.  If the
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
** function returns SQLITE_ERROR.
**
** The deserialized database should not be in [WAL mode].  If the database
** is in WAL mode, then any attempt to use the database file will result
** in an [SQLITE_CANTOPEN] error.  The application can set the
** [file format version numbers] (bytes 18 and 19) of the input database P
** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the
** database file into rollback mode and work around this limitation.
**
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
10798
10799
10800
10801
10802
10803
10804
10805

10806
10807
10808
10809
10810


10811




10812

10813
10814

10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833












10834
10835


10836
10837
10838
10839
10840
10841
10842
10995
10996
10997
10998
10999
11000
11001

11002
11003
11004
11005


11006
11007
11008
11009
11010
11011
11012

11013
11014

11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030




11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043

11044
11045
11046
11047
11048
11049
11050
11051
11052







-
+



-
-
+
+

+
+
+
+
-
+

-
+















-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+







** Session objects must be deleted before the database handle to which they
** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);

/*
** CAPIREF: Conigure a Session Object
** CAPI3REF: Configure a Session Object
** METHOD: sqlite3_session
**
** This method is used to configure a session object after it has been
** created. At present the only valid value for the second parameter is
** [SQLITE_SESSION_OBJCONFIG_SIZE].
** created. At present the only valid values for the second parameter are
** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID].
**
*/
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);

/*
** Arguments for sqlite3session_object_config()
** CAPI3REF: Options for sqlite3session_object_config
**
** The following values may passed as the the 4th parameter to
** The following values may passed as the the 2nd parameter to
** sqlite3session_object_config().
**
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
**   This option is used to set, clear or query the flag that enables
**   the [sqlite3session_changeset_size()] API. Because it imposes some
**   computational overhead, this API is disabled by default. Argument
**   pArg must point to a value of type (int). If the value is initially
**   0, then the sqlite3session_changeset_size() API is disabled. If it
**   is greater than 0, then the same API is enabled. Or, if the initial
**   value is less than zero, no change is made. In all cases the (int)
**   variable is set to 1 if the sqlite3session_changeset_size() API is
**   enabled following the current call, or 0 otherwise.
**
**   It is an error (SQLITE_MISUSE) to attempt to modify this setting after
**   the first table has been attached to the session object.
*/
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);

/*
**
** <dt>SQLITE_SESSION_OBJCONFIG_ROWID <dd>
**   This option is used to set, clear or query the flag that enables
**   collection of data for tables with no explicit PRIMARY KEY.
**
**   Normally, tables with no explicit PRIMARY KEY are simply ignored
**   by the sessions module. However, if this flag is set, it behaves
**   as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted
**   as their leftmost columns.
**
**   It is an error (SQLITE_MISUSE) to attempt to modify this setting after
**   the first table has been attached to the session object.
*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
#define SQLITE_SESSION_OBJCONFIG_SIZE  1
#define SQLITE_SESSION_OBJCONFIG_ROWID 2

/*
** CAPI3REF: Enable Or Disable A Session Object
** METHOD: sqlite3_session
**
** Enable or disable the recording of changes by a session object. When
** enabled, a session object records changes made to the database. When
11588
11589
11590
11591
11592
11593
11594












11595
11596
11597
11598
11599
11600
11601
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823







+
+
+
+
+
+
+
+
+
+
+
+







  void *pA,                       /* Pointer to buffer containing changeset A */
  int nB,                         /* Number of bytes in buffer pB */
  void *pB,                       /* Pointer to buffer containing changeset B */
  int *pnOut,                     /* OUT: Number of bytes in output changeset */
  void **ppOut                    /* OUT: Buffer containing output changeset */
);


/*
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
*/
SQLITE_API int sqlite3changeset_upgrade(
  sqlite3 *db,
  const char *zDb,
  int nIn, const void *pIn,       /* Input changeset */
  int *pnOut, void **ppOut        /* OUT: Inverse of input */
);



/*
** CAPI3REF: Changegroup Handle
**
** A changegroup is an object used to combine two or more
** [changesets] or [patchsets]
*/
11635
11636
11637
11638
11639
11640
11641
































11642
11643
11644
11645
11646
11647
11648
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







**
** As well as the regular sqlite3changegroup_add() and
** sqlite3changegroup_output() functions, also available are the streaming
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);

/*
** CAPI3REF: Add a Schema to a Changegroup
** METHOD: sqlite3_changegroup_schema
**
** This method may be used to optionally enforce the rule that the changesets
** added to the changegroup handle must match the schema of database zDb
** ("main", "temp", or the name of an attached database). If
** sqlite3changegroup_add() is called to add a changeset that is not compatible
** with the configured schema, SQLITE_SCHEMA is returned and the changegroup
** object is left in an undefined state.
**
** A changeset schema is considered compatible with the database schema in
** the same way as for sqlite3changeset_apply(). Specifically, for each
** table in the changeset, there exists a database table with:
**
** <ul>
**   <li> The name identified by the changeset, and
**   <li> at least as many columns as recorded in the changeset, and
**   <li> the primary key columns in the same position as recorded in
**        the changeset.
** </ul>
**
** The output of the changegroup object always has the same schema as the
** database nominated using this function. In cases where changesets passed
** to sqlite3changegroup_add() have fewer columns than the corresponding table
** in the database schema, these are filled in using the default column
** values from the database schema. This makes it possible to combined
** changesets that have different numbers of columns for a single table
** within a changegroup, provided that they are otherwise compatible.
*/
SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);

/*
** CAPI3REF: Add A Changeset To A Changegroup
** METHOD: sqlite3_changegroup
**
** Add all changes within the changeset (or patchset) in buffer pData (size
** nData bytes) to the changegroup.
**
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713









11714
11715

11716

11717
11718
11719
11720
11721
11722
11723
11957
11958
11959
11960
11961
11962
11963




11964
11965
11966
11967
11968
11969
11970
11971
11972

11973
11974

11975
11976
11977
11978
11979
11980
11981
11982







-
-
-
-
+
+
+
+
+
+
+
+
+
-

+
-
+







**       changeset was recorded immediately after the changesets already
**       added to the changegroup.
** </table>
**
** If the new changeset contains changes to a table that is already present
** in the changegroup, then the number of columns and the position of the
** primary key columns for the table must be consistent. If this is not the
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup
** object has been configured with a database schema using the
** sqlite3changegroup_schema() API, then it is possible to combine changesets
** with different numbers of columns for a single table, provided that
** they are otherwise compatible.
**
** If the input changeset appears to be corrupt and the corruption is
** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition
** occurs during processing, this function returns SQLITE_NOMEM.
** of the final contents of the changegroup is undefined.
**
** In all cases, if an error occurs the state of the final contents of the
** If no error occurs, SQLITE_OK is returned.
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
*/
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);

/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
** METHOD: sqlite3_changegroup
**
11974
11975
11976
11977
11978
11979
11980






11981
11982
11983
11984

11985
11986
11987
11988
11989
11990
11991
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257







+
+
+
+
+
+




+







**    <ul>
**    <li>a delete change if the row being deleted cannot be found,
**    <li>an update change if the modified fields are already set to
**        their new values in the conflicting row, or
**    <li>an insert change if all fields of the conflicting row match
**        the row being inserted.
**    </ul>
**
** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>
**   If this flag it set, then all foreign key constraints in the target
**   database behave as if they were declared with "ON UPDATE NO ACTION ON
**   DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
**   or SET DEFAULT.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT   0x0001
#define SQLITE_CHANGESETAPPLY_INVERT        0x0002
#define SQLITE_CHANGESETAPPLY_IGNORENOOP    0x0004
#define SQLITE_CHANGESETAPPLY_FKNOACTION    0x0008

/*
** CAPI3REF: Constants Passed To The Conflict Handler
**
** Values that may be passed as the second argument to a conflict-handler.
**
** <dl>
12718
12719
12720
12721
12722
12723
12724
12725

12726
12727
12728
12729
12730
12731
12732
12984
12985
12986
12987
12988
12989
12990

12991
12992
12993
12994
12995
12996
12997
12998







-
+







**   significantly more efficient than those alternatives when used with
**   "detail=column" tables.
**
** xPhraseNextColumn()
**   See xPhraseFirstColumn above.
*/
struct Fts5ExtensionApi {
  int iVersion;                   /* Currently always set to 3 */
  int iVersion;                   /* Currently always set to 2 */

  void *(*xUserData)(Fts5Context*);

  int (*xColumnCount)(Fts5Context*);
  int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
  int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);

12947
12948
12949
12950
12951
12952
12953
12954
12955


12956
12957
12958
12959
12960
12961
12962
13213
13214
13215
13216
13217
13218
13219


13220
13221
13222
13223
13224
13225
13226
13227
13228







-
-
+
+







**   provide synonyms for prefixes). However, a non-prefix query like '1st'
**   will match against "1st" and "first". This method does not require
**   extra disk space, as no extra entries are added to the FTS index.
**   On the other hand, it may require more CPU cycles to run MATCH queries,
**   as separate queries of the FTS index are required for each synonym.
**
**   When using methods (2) or (3), it is important that the tokenizer only
**   provide synonyms when tokenizing document text (method (2)) or query
**   text (method (3)), not both. Doing so will not cause any errors, but is
**   provide synonyms when tokenizing document text (method (3)) or query
**   text (method (2)), not both. Doing so will not cause any errors, but is
**   inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
  void (*xDelete)(Fts5Tokenizer*);
12996
12997
12998
12999
13000
13001
13002
13003

13004
13005
13006
13007
13008
13009
13010
13011
13012

13013
13014
13015
13016
13017
13018
13019
13020

13021
13022
13023
13024
13025
13026
13027
13262
13263
13264
13265
13266
13267
13268

13269
13270
13271
13272
13273
13274
13275
13276
13277

13278
13279
13280
13281
13282
13283
13284
13285

13286
13287
13288
13289
13290
13291
13292
13293







-
+








-
+







-
+







struct fts5_api {
  int iVersion;                   /* Currently always set to 2 */

  /* Create a new tokenizer */
  int (*xCreateTokenizer)(
    fts5_api *pApi,
    const char *zName,
    void *pContext,
    void *pUserData,
    fts5_tokenizer *pTokenizer,
    void (*xDestroy)(void*)
  );

  /* Find an existing tokenizer */
  int (*xFindTokenizer)(
    fts5_api *pApi,
    const char *zName,
    void **ppContext,
    void **ppUserData,
    fts5_tokenizer *pTokenizer
  );

  /* Create a new auxiliary function */
  int (*xCreateFunction)(
    fts5_api *pApi,
    const char *zName,
    void *pContext,
    void *pUserData,
    fts5_extension_function xFunction,
    void (*xDestroy)(void*)
  );
};

/*
** END OF REGISTRATION API

Deleted lib/sqlite3ext.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709





































































































































































































































































































































































































































































































































































































































































































































-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
** 2006 June 7
**
** 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 header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance.  Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of 
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"

/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING:  In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only.  If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
  void * (*aggregate_context)(sqlite3_context*,int nBytes);
  int  (*aggregate_count)(sqlite3_context*);
  int  (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
  int  (*bind_double)(sqlite3_stmt*,int,double);
  int  (*bind_int)(sqlite3_stmt*,int,int);
  int  (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
  int  (*bind_null)(sqlite3_stmt*,int);
  int  (*bind_parameter_count)(sqlite3_stmt*);
  int  (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
  const char * (*bind_parameter_name)(sqlite3_stmt*,int);
  int  (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
  int  (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
  int  (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
  int  (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
  int  (*busy_timeout)(sqlite3*,int ms);
  int  (*changes)(sqlite3*);
  int  (*close)(sqlite3*);
  int  (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
                           int eTextRep,const char*));
  int  (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
                             int eTextRep,const void*));
  const void * (*column_blob)(sqlite3_stmt*,int iCol);
  int  (*column_bytes)(sqlite3_stmt*,int iCol);
  int  (*column_bytes16)(sqlite3_stmt*,int iCol);
  int  (*column_count)(sqlite3_stmt*pStmt);
  const char * (*column_database_name)(sqlite3_stmt*,int);
  const void * (*column_database_name16)(sqlite3_stmt*,int);
  const char * (*column_decltype)(sqlite3_stmt*,int i);
  const void * (*column_decltype16)(sqlite3_stmt*,int);
  double  (*column_double)(sqlite3_stmt*,int iCol);
  int  (*column_int)(sqlite3_stmt*,int iCol);
  sqlite_int64  (*column_int64)(sqlite3_stmt*,int iCol);
  const char * (*column_name)(sqlite3_stmt*,int);
  const void * (*column_name16)(sqlite3_stmt*,int);
  const char * (*column_origin_name)(sqlite3_stmt*,int);
  const void * (*column_origin_name16)(sqlite3_stmt*,int);
  const char * (*column_table_name)(sqlite3_stmt*,int);
  const void * (*column_table_name16)(sqlite3_stmt*,int);
  const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
  const void * (*column_text16)(sqlite3_stmt*,int iCol);
  int  (*column_type)(sqlite3_stmt*,int iCol);
  sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
  void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
  int  (*complete)(const char*sql);
  int  (*complete16)(const void*sql);
  int  (*create_collation)(sqlite3*,const char*,int,void*,
                           int(*)(void*,int,const void*,int,const void*));
  int  (*create_collation16)(sqlite3*,const void*,int,void*,
                             int(*)(void*,int,const void*,int,const void*));
  int  (*create_function)(sqlite3*,const char*,int,int,void*,
                          void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                          void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                          void (*xFinal)(sqlite3_context*));
  int  (*create_function16)(sqlite3*,const void*,int,int,void*,
                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*));
  int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
  int  (*data_count)(sqlite3_stmt*pStmt);
  sqlite3 * (*db_handle)(sqlite3_stmt*);
  int (*declare_vtab)(sqlite3*,const char*);
  int  (*enable_shared_cache)(int);
  int  (*errcode)(sqlite3*db);
  const char * (*errmsg)(sqlite3*);
  const void * (*errmsg16)(sqlite3*);
  int  (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
  int  (*expired)(sqlite3_stmt*);
  int  (*finalize)(sqlite3_stmt*pStmt);
  void  (*free)(void*);
  void  (*free_table)(char**result);
  int  (*get_autocommit)(sqlite3*);
  void * (*get_auxdata)(sqlite3_context*,int);
  int  (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
  int  (*global_recover)(void);
  void  (*interruptx)(sqlite3*);
  sqlite_int64  (*last_insert_rowid)(sqlite3*);
  const char * (*libversion)(void);
  int  (*libversion_number)(void);
  void *(*malloc)(int);
  char * (*mprintf)(const char*,...);
  int  (*open)(const char*,sqlite3**);
  int  (*open16)(const void*,sqlite3**);
  int  (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
  int  (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
  void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
  void  (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
  void *(*realloc)(void*,int);
  int  (*reset)(sqlite3_stmt*pStmt);
  void  (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_double)(sqlite3_context*,double);
  void  (*result_error)(sqlite3_context*,const char*,int);
  void  (*result_error16)(sqlite3_context*,const void*,int);
  void  (*result_int)(sqlite3_context*,int);
  void  (*result_int64)(sqlite3_context*,sqlite_int64);
  void  (*result_null)(sqlite3_context*);
  void  (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
  void  (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_value)(sqlite3_context*,sqlite3_value*);
  void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
  int  (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
                         const char*,const char*),void*);
  void  (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
  char * (*xsnprintf)(int,char*,const char*,...);
  int  (*step)(sqlite3_stmt*);
  int  (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
                                char const**,char const**,int*,int*,int*);
  void  (*thread_cleanup)(void);
  int  (*total_changes)(sqlite3*);
  void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
  int  (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
  void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
                                         sqlite_int64),void*);
  void * (*user_data)(sqlite3_context*);
  const void * (*value_blob)(sqlite3_value*);
  int  (*value_bytes)(sqlite3_value*);
  int  (*value_bytes16)(sqlite3_value*);
  double  (*value_double)(sqlite3_value*);
  int  (*value_int)(sqlite3_value*);
  sqlite_int64  (*value_int64)(sqlite3_value*);
  int  (*value_numeric_type)(sqlite3_value*);
  const unsigned char * (*value_text)(sqlite3_value*);
  const void * (*value_text16)(sqlite3_value*);
  const void * (*value_text16be)(sqlite3_value*);
  const void * (*value_text16le)(sqlite3_value*);
  int  (*value_type)(sqlite3_value*);
  char *(*vmprintf)(const char*,va_list);
  /* Added ??? */
  int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
  /* Added by 3.3.13 */
  int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
  int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
  int (*clear_bindings)(sqlite3_stmt*);
  /* Added by 3.4.1 */
  int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
                          void (*xDestroy)(void *));
  /* Added by 3.5.0 */
  int (*bind_zeroblob)(sqlite3_stmt*,int,int);
  int (*blob_bytes)(sqlite3_blob*);
  int (*blob_close)(sqlite3_blob*);
  int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
                   int,sqlite3_blob**);
  int (*blob_read)(sqlite3_blob*,void*,int,int);
  int (*blob_write)(sqlite3_blob*,const void*,int,int);
  int (*create_collation_v2)(sqlite3*,const char*,int,void*,
                             int(*)(void*,int,const void*,int,const void*),
                             void(*)(void*));
  int (*file_control)(sqlite3*,const char*,int,void*);
  sqlite3_int64 (*memory_highwater)(int);
  sqlite3_int64 (*memory_used)(void);
  sqlite3_mutex *(*mutex_alloc)(int);
  void (*mutex_enter)(sqlite3_mutex*);
  void (*mutex_free)(sqlite3_mutex*);
  void (*mutex_leave)(sqlite3_mutex*);
  int (*mutex_try)(sqlite3_mutex*);
  int (*open_v2)(const char*,sqlite3**,int,const char*);
  int (*release_memory)(int);
  void (*result_error_nomem)(sqlite3_context*);
  void (*result_error_toobig)(sqlite3_context*);
  int (*sleep)(int);
  void (*soft_heap_limit)(int);
  sqlite3_vfs *(*vfs_find)(const char*);
  int (*vfs_register)(sqlite3_vfs*,int);
  int (*vfs_unregister)(sqlite3_vfs*);
  int (*xthreadsafe)(void);
  void (*result_zeroblob)(sqlite3_context*,int);
  void (*result_error_code)(sqlite3_context*,int);
  int (*test_control)(int, ...);
  void (*randomness)(int,void*);
  sqlite3 *(*context_db_handle)(sqlite3_context*);
  int (*extended_result_codes)(sqlite3*,int);
  int (*limit)(sqlite3*,int,int);
  sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
  const char *(*sql)(sqlite3_stmt*);
  int (*status)(int,int*,int*,int);
  int (*backup_finish)(sqlite3_backup*);
  sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
  int (*backup_pagecount)(sqlite3_backup*);
  int (*backup_remaining)(sqlite3_backup*);
  int (*backup_step)(sqlite3_backup*,int);
  const char *(*compileoption_get)(int);
  int (*compileoption_used)(const char*);
  int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*),
                            void(*xDestroy)(void*));
  int (*db_config)(sqlite3*,int,...);
  sqlite3_mutex *(*db_mutex)(sqlite3*);
  int (*db_status)(sqlite3*,int,int*,int*,int);
  int (*extended_errcode)(sqlite3*);
  void (*log)(int,const char*,...);
  sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
  const char *(*sourceid)(void);
  int (*stmt_status)(sqlite3_stmt*,int,int);
  int (*strnicmp)(const char*,const char*,int);
  int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
  int (*wal_autocheckpoint)(sqlite3*,int);
  int (*wal_checkpoint)(sqlite3*,const char*);
  void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
  int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
  int (*vtab_config)(sqlite3*,int op,...);
  int (*vtab_on_conflict)(sqlite3*);
  /* Version 3.7.16 and later */
  int (*close_v2)(sqlite3*);
  const char *(*db_filename)(sqlite3*,const char*);
  int (*db_readonly)(sqlite3*,const char*);
  int (*db_release_memory)(sqlite3*);
  const char *(*errstr)(int);
  int (*stmt_busy)(sqlite3_stmt*);
  int (*stmt_readonly)(sqlite3_stmt*);
  int (*stricmp)(const char*,const char*);
  int (*uri_boolean)(const char*,const char*,int);
  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
  const char *(*uri_parameter)(const char*,const char*);
  char *(*xvsnprintf)(int,char*,const char*,va_list);
  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
  /* Version 3.8.7 and later */
  int (*auto_extension)(void(*)(void));
  int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
                     void(*)(void*));
  int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
                      void(*)(void*),unsigned char);
  int (*cancel_auto_extension)(void(*)(void));
  int (*load_extension)(sqlite3*,const char*,const char*,char**);
  void *(*malloc64)(sqlite3_uint64);
  sqlite3_uint64 (*msize)(void*);
  void *(*realloc64)(void*,sqlite3_uint64);
  void (*reset_auto_extension)(void);
  void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
                        void(*)(void*));
  void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
                         void(*)(void*), unsigned char);
  int (*strglob)(const char*,const char*);
  /* Version 3.8.11 and later */
  sqlite3_value *(*value_dup)(const sqlite3_value*);
  void (*value_free)(sqlite3_value*);
  int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
  int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
  /* Version 3.9.0 and later */
  unsigned int (*value_subtype)(sqlite3_value*);
  void (*result_subtype)(sqlite3_context*,unsigned int);
  /* Version 3.10.0 and later */
  int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
  int (*strlike)(const char*,const char*,unsigned int);
  int (*db_cacheflush)(sqlite3*);
  /* Version 3.12.0 and later */
  int (*system_errno)(sqlite3*);
  /* Version 3.14.0 and later */
  int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
  char *(*expanded_sql)(sqlite3_stmt*);
  /* Version 3.18.0 and later */
  void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
  /* Version 3.20.0 and later */
  int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
                    sqlite3_stmt**,const char**);
  int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
                      sqlite3_stmt**,const void**);
  int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
  void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
  void *(*value_pointer)(sqlite3_value*,const char*);
  int (*vtab_nochange)(sqlite3_context*);
  int (*value_nochange)(sqlite3_value*);
  const char *(*vtab_collation)(sqlite3_index_info*,int);
  /* Version 3.24.0 and later */
  int (*keyword_count)(void);
  int (*keyword_name)(int,const char**,int*);
  int (*keyword_check)(const char*,int);
  sqlite3_str *(*str_new)(sqlite3*);
  char *(*str_finish)(sqlite3_str*);
  void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
  void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
  void (*str_append)(sqlite3_str*, const char *zIn, int N);
  void (*str_appendall)(sqlite3_str*, const char *zIn);
  void (*str_appendchar)(sqlite3_str*, int N, char C);
  void (*str_reset)(sqlite3_str*);
  int (*str_errcode)(sqlite3_str*);
  int (*str_length)(sqlite3_str*);
  char *(*str_value)(sqlite3_str*);
  /* Version 3.25.0 and later */
  int (*create_window_function)(sqlite3*,const char*,int,int,void*,
                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*),
                            void (*xValue)(sqlite3_context*),
                            void (*xInv)(sqlite3_context*,int,sqlite3_value**),
                            void(*xDestroy)(void*));
  /* Version 3.26.0 and later */
  const char *(*normalized_sql)(sqlite3_stmt*);
  /* Version 3.28.0 and later */
  int (*stmt_isexplain)(sqlite3_stmt*);
  int (*value_frombind)(sqlite3_value*);
  /* Version 3.30.0 and later */
  int (*drop_modules)(sqlite3*,const char**);
  /* Version 3.31.0 and later */
  sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
  const char *(*uri_key)(const char*,int);
  const char *(*filename_database)(const char*);
  const char *(*filename_journal)(const char*);
  const char *(*filename_wal)(const char*);
  /* Version 3.32.0 and later */
  const char *(*create_filename)(const char*,const char*,const char*,
                           int,const char**);
  void (*free_filename)(const char*);
  sqlite3_file *(*database_file_object)(const char*);
  /* Version 3.34.0 and later */
  int (*txn_state)(sqlite3*,const char*);
  /* Version 3.36.1 and later */
  sqlite3_int64 (*changes64)(sqlite3*);
  sqlite3_int64 (*total_changes64)(sqlite3*);
  /* Version 3.37.0 and later */
  int (*autovacuum_pages)(sqlite3*,
     unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
     void*, void(*)(void*));
  /* Version 3.38.0 and later */
  int (*error_offset)(sqlite3*);
  int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
  int (*vtab_distinct)(sqlite3_index_info*);
  int (*vtab_in)(sqlite3_index_info*,int,int);
  int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
  int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
  /* Version 3.39.0 and later */
  int (*deserialize)(sqlite3*,const char*,unsigned char*,
                     sqlite3_int64,sqlite3_int64,unsigned);
  unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
                              unsigned int);
  const char *(*db_name)(sqlite3*,int);
  /* Version 3.40.0 and later */
  int (*value_encoding)(sqlite3_value*);
  /* Version 3.41.0 and later */
  int (*is_interrupted)(sqlite3*);
};

/*
** This is the function signature used for all extension entry points.  It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
  sqlite3 *db,                       /* Handle to the database. */
  char **pzErrMsg,                   /* Used to set error string on failure. */
  const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);

/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition.  But the main library does not want to redefine
** the API.  So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context      sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count        sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob              sqlite3_api->bind_blob
#define sqlite3_bind_double            sqlite3_api->bind_double
#define sqlite3_bind_int               sqlite3_api->bind_int
#define sqlite3_bind_int64             sqlite3_api->bind_int64
#define sqlite3_bind_null              sqlite3_api->bind_null
#define sqlite3_bind_parameter_count   sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index   sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name    sqlite3_api->bind_parameter_name
#define sqlite3_bind_text              sqlite3_api->bind_text
#define sqlite3_bind_text16            sqlite3_api->bind_text16
#define sqlite3_bind_value             sqlite3_api->bind_value
#define sqlite3_busy_handler           sqlite3_api->busy_handler
#define sqlite3_busy_timeout           sqlite3_api->busy_timeout
#define sqlite3_changes                sqlite3_api->changes
#define sqlite3_close                  sqlite3_api->close
#define sqlite3_collation_needed       sqlite3_api->collation_needed
#define sqlite3_collation_needed16     sqlite3_api->collation_needed16
#define sqlite3_column_blob            sqlite3_api->column_blob
#define sqlite3_column_bytes           sqlite3_api->column_bytes
#define sqlite3_column_bytes16         sqlite3_api->column_bytes16
#define sqlite3_column_count           sqlite3_api->column_count
#define sqlite3_column_database_name   sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype        sqlite3_api->column_decltype
#define sqlite3_column_decltype16      sqlite3_api->column_decltype16
#define sqlite3_column_double          sqlite3_api->column_double
#define sqlite3_column_int             sqlite3_api->column_int
#define sqlite3_column_int64           sqlite3_api->column_int64
#define sqlite3_column_name            sqlite3_api->column_name
#define sqlite3_column_name16          sqlite3_api->column_name16
#define sqlite3_column_origin_name     sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16   sqlite3_api->column_origin_name16
#define sqlite3_column_table_name      sqlite3_api->column_table_name
#define sqlite3_column_table_name16    sqlite3_api->column_table_name16
#define sqlite3_column_text            sqlite3_api->column_text
#define sqlite3_column_text16          sqlite3_api->column_text16
#define sqlite3_column_type            sqlite3_api->column_type
#define sqlite3_column_value           sqlite3_api->column_value
#define sqlite3_commit_hook            sqlite3_api->commit_hook
#define sqlite3_complete               sqlite3_api->complete
#define sqlite3_complete16             sqlite3_api->complete16
#define sqlite3_create_collation       sqlite3_api->create_collation
#define sqlite3_create_collation16     sqlite3_api->create_collation16
#define sqlite3_create_function        sqlite3_api->create_function
#define sqlite3_create_function16      sqlite3_api->create_function16
#define sqlite3_create_module          sqlite3_api->create_module
#define sqlite3_create_module_v2       sqlite3_api->create_module_v2
#define sqlite3_data_count             sqlite3_api->data_count
#define sqlite3_db_handle              sqlite3_api->db_handle
#define sqlite3_declare_vtab           sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache    sqlite3_api->enable_shared_cache
#define sqlite3_errcode                sqlite3_api->errcode
#define sqlite3_errmsg                 sqlite3_api->errmsg
#define sqlite3_errmsg16               sqlite3_api->errmsg16
#define sqlite3_exec                   sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired                sqlite3_api->expired
#endif
#define sqlite3_finalize               sqlite3_api->finalize
#define sqlite3_free                   sqlite3_api->free
#define sqlite3_free_table             sqlite3_api->free_table
#define sqlite3_get_autocommit         sqlite3_api->get_autocommit
#define sqlite3_get_auxdata            sqlite3_api->get_auxdata
#define sqlite3_get_table              sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover         sqlite3_api->global_recover
#endif
#define sqlite3_interrupt              sqlite3_api->interruptx
#define sqlite3_last_insert_rowid      sqlite3_api->last_insert_rowid
#define sqlite3_libversion             sqlite3_api->libversion
#define sqlite3_libversion_number      sqlite3_api->libversion_number
#define sqlite3_malloc                 sqlite3_api->malloc
#define sqlite3_mprintf                sqlite3_api->mprintf
#define sqlite3_open                   sqlite3_api->open
#define sqlite3_open16                 sqlite3_api->open16
#define sqlite3_prepare                sqlite3_api->prepare
#define sqlite3_prepare16              sqlite3_api->prepare16
#define sqlite3_prepare_v2             sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2           sqlite3_api->prepare16_v2
#define sqlite3_profile                sqlite3_api->profile
#define sqlite3_progress_handler       sqlite3_api->progress_handler
#define sqlite3_realloc                sqlite3_api->realloc
#define sqlite3_reset                  sqlite3_api->reset
#define sqlite3_result_blob            sqlite3_api->result_blob
#define sqlite3_result_double          sqlite3_api->result_double
#define sqlite3_result_error           sqlite3_api->result_error
#define sqlite3_result_error16         sqlite3_api->result_error16
#define sqlite3_result_int             sqlite3_api->result_int
#define sqlite3_result_int64           sqlite3_api->result_int64
#define sqlite3_result_null            sqlite3_api->result_null
#define sqlite3_result_text            sqlite3_api->result_text
#define sqlite3_result_text16          sqlite3_api->result_text16
#define sqlite3_result_text16be        sqlite3_api->result_text16be
#define sqlite3_result_text16le        sqlite3_api->result_text16le
#define sqlite3_result_value           sqlite3_api->result_value
#define sqlite3_rollback_hook          sqlite3_api->rollback_hook
#define sqlite3_set_authorizer         sqlite3_api->set_authorizer
#define sqlite3_set_auxdata            sqlite3_api->set_auxdata
#define sqlite3_snprintf               sqlite3_api->xsnprintf
#define sqlite3_step                   sqlite3_api->step
#define sqlite3_table_column_metadata  sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup         sqlite3_api->thread_cleanup
#define sqlite3_total_changes          sqlite3_api->total_changes
#define sqlite3_trace                  sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings      sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook            sqlite3_api->update_hook
#define sqlite3_user_data              sqlite3_api->user_data
#define sqlite3_value_blob             sqlite3_api->value_blob
#define sqlite3_value_bytes            sqlite3_api->value_bytes
#define sqlite3_value_bytes16          sqlite3_api->value_bytes16
#define sqlite3_value_double           sqlite3_api->value_double
#define sqlite3_value_int              sqlite3_api->value_int
#define sqlite3_value_int64            sqlite3_api->value_int64
#define sqlite3_value_numeric_type     sqlite3_api->value_numeric_type
#define sqlite3_value_text             sqlite3_api->value_text
#define sqlite3_value_text16           sqlite3_api->value_text16
#define sqlite3_value_text16be         sqlite3_api->value_text16be
#define sqlite3_value_text16le         sqlite3_api->value_text16le
#define sqlite3_value_type             sqlite3_api->value_type
#define sqlite3_vmprintf               sqlite3_api->vmprintf
#define sqlite3_vsnprintf              sqlite3_api->xvsnprintf
#define sqlite3_overload_function      sqlite3_api->overload_function
#define sqlite3_prepare_v2             sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2           sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings         sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob          sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes             sqlite3_api->blob_bytes
#define sqlite3_blob_close             sqlite3_api->blob_close
#define sqlite3_blob_open              sqlite3_api->blob_open
#define sqlite3_blob_read              sqlite3_api->blob_read
#define sqlite3_blob_write             sqlite3_api->blob_write
#define sqlite3_create_collation_v2    sqlite3_api->create_collation_v2
#define sqlite3_file_control           sqlite3_api->file_control
#define sqlite3_memory_highwater       sqlite3_api->memory_highwater
#define sqlite3_memory_used            sqlite3_api->memory_used
#define sqlite3_mutex_alloc            sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter            sqlite3_api->mutex_enter
#define sqlite3_mutex_free             sqlite3_api->mutex_free
#define sqlite3_mutex_leave            sqlite3_api->mutex_leave
#define sqlite3_mutex_try              sqlite3_api->mutex_try
#define sqlite3_open_v2                sqlite3_api->open_v2
#define sqlite3_release_memory         sqlite3_api->release_memory
#define sqlite3_result_error_nomem     sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig    sqlite3_api->result_error_toobig
#define sqlite3_sleep                  sqlite3_api->sleep
#define sqlite3_soft_heap_limit        sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find               sqlite3_api->vfs_find
#define sqlite3_vfs_register           sqlite3_api->vfs_register
#define sqlite3_vfs_unregister         sqlite3_api->vfs_unregister
#define sqlite3_threadsafe             sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob        sqlite3_api->result_zeroblob
#define sqlite3_result_error_code      sqlite3_api->result_error_code
#define sqlite3_test_control           sqlite3_api->test_control
#define sqlite3_randomness             sqlite3_api->randomness
#define sqlite3_context_db_handle      sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes  sqlite3_api->extended_result_codes
#define sqlite3_limit                  sqlite3_api->limit
#define sqlite3_next_stmt              sqlite3_api->next_stmt
#define sqlite3_sql                    sqlite3_api->sql
#define sqlite3_status                 sqlite3_api->status
#define sqlite3_backup_finish          sqlite3_api->backup_finish
#define sqlite3_backup_init            sqlite3_api->backup_init
#define sqlite3_backup_pagecount       sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining       sqlite3_api->backup_remaining
#define sqlite3_backup_step            sqlite3_api->backup_step
#define sqlite3_compileoption_get      sqlite3_api->compileoption_get
#define sqlite3_compileoption_used     sqlite3_api->compileoption_used
#define sqlite3_create_function_v2     sqlite3_api->create_function_v2
#define sqlite3_db_config              sqlite3_api->db_config
#define sqlite3_db_mutex               sqlite3_api->db_mutex
#define sqlite3_db_status              sqlite3_api->db_status
#define sqlite3_extended_errcode       sqlite3_api->extended_errcode
#define sqlite3_log                    sqlite3_api->log
#define sqlite3_soft_heap_limit64      sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid               sqlite3_api->sourceid
#define sqlite3_stmt_status            sqlite3_api->stmt_status
#define sqlite3_strnicmp               sqlite3_api->strnicmp
#define sqlite3_unlock_notify          sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint     sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint         sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook               sqlite3_api->wal_hook
#define sqlite3_blob_reopen            sqlite3_api->blob_reopen
#define sqlite3_vtab_config            sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2               sqlite3_api->close_v2
#define sqlite3_db_filename            sqlite3_api->db_filename
#define sqlite3_db_readonly            sqlite3_api->db_readonly
#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
#define sqlite3_errstr                 sqlite3_api->errstr
#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
#define sqlite3_stricmp                sqlite3_api->stricmp
#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
#define sqlite3_uri_int64              sqlite3_api->uri_int64
#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf          sqlite3_api->xvsnprintf
#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension         sqlite3_api->auto_extension
#define sqlite3_bind_blob64            sqlite3_api->bind_blob64
#define sqlite3_bind_text64            sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension  sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension         sqlite3_api->load_extension
#define sqlite3_malloc64               sqlite3_api->malloc64
#define sqlite3_msize                  sqlite3_api->msize
#define sqlite3_realloc64              sqlite3_api->realloc64
#define sqlite3_reset_auto_extension   sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64          sqlite3_api->result_blob64
#define sqlite3_result_text64          sqlite3_api->result_text64
#define sqlite3_strglob                sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup              sqlite3_api->value_dup
#define sqlite3_value_free             sqlite3_api->value_free
#define sqlite3_result_zeroblob64      sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64        sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype          sqlite3_api->value_subtype
#define sqlite3_result_subtype         sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64               sqlite3_api->status64
#define sqlite3_strlike                sqlite3_api->strlike
#define sqlite3_db_cacheflush          sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno           sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2               sqlite3_api->trace_v2
#define sqlite3_expanded_sql           sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid  sqlite3_api->set_last_insert_rowid
/* Version 3.20.0 and later */
#define sqlite3_prepare_v3             sqlite3_api->prepare_v3
#define sqlite3_prepare16_v3           sqlite3_api->prepare16_v3
#define sqlite3_bind_pointer           sqlite3_api->bind_pointer
#define sqlite3_result_pointer         sqlite3_api->result_pointer
#define sqlite3_value_pointer          sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange          sqlite3_api->vtab_nochange
#define sqlite3_value_nochange         sqlite3_api->value_nochange
#define sqlite3_vtab_collation         sqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define sqlite3_keyword_count          sqlite3_api->keyword_count
#define sqlite3_keyword_name           sqlite3_api->keyword_name
#define sqlite3_keyword_check          sqlite3_api->keyword_check
#define sqlite3_str_new                sqlite3_api->str_new
#define sqlite3_str_finish             sqlite3_api->str_finish
#define sqlite3_str_appendf            sqlite3_api->str_appendf
#define sqlite3_str_vappendf           sqlite3_api->str_vappendf
#define sqlite3_str_append             sqlite3_api->str_append
#define sqlite3_str_appendall          sqlite3_api->str_appendall
#define sqlite3_str_appendchar         sqlite3_api->str_appendchar
#define sqlite3_str_reset              sqlite3_api->str_reset
#define sqlite3_str_errcode            sqlite3_api->str_errcode
#define sqlite3_str_length             sqlite3_api->str_length
#define sqlite3_str_value              sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql         sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define sqlite3_stmt_isexplain         sqlite3_api->stmt_isexplain
#define sqlite3_value_frombind         sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules           sqlite3_api->drop_modules
/* Version 3.31.0 and later */
#define sqlite3_hard_heap_limit64      sqlite3_api->hard_heap_limit64
#define sqlite3_uri_key                sqlite3_api->uri_key
#define sqlite3_filename_database      sqlite3_api->filename_database
#define sqlite3_filename_journal       sqlite3_api->filename_journal
#define sqlite3_filename_wal           sqlite3_api->filename_wal
/* Version 3.32.0 and later */
#define sqlite3_create_filename        sqlite3_api->create_filename
#define sqlite3_free_filename          sqlite3_api->free_filename
#define sqlite3_database_file_object   sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlite3_txn_state              sqlite3_api->txn_state
/* Version 3.36.1 and later */
#define sqlite3_changes64              sqlite3_api->changes64
#define sqlite3_total_changes64        sqlite3_api->total_changes64
/* Version 3.37.0 and later */
#define sqlite3_autovacuum_pages       sqlite3_api->autovacuum_pages
/* Version 3.38.0 and later */
#define sqlite3_error_offset           sqlite3_api->error_offset
#define sqlite3_vtab_rhs_value         sqlite3_api->vtab_rhs_value
#define sqlite3_vtab_distinct          sqlite3_api->vtab_distinct
#define sqlite3_vtab_in                sqlite3_api->vtab_in
#define sqlite3_vtab_in_first          sqlite3_api->vtab_in_first
#define sqlite3_vtab_in_next           sqlite3_api->vtab_in_next
/* Version 3.39.0 and later */
#ifndef SQLITE_OMIT_DESERIALIZE
#define sqlite3_deserialize            sqlite3_api->deserialize
#define sqlite3_serialize              sqlite3_api->serialize
#endif
#define sqlite3_db_name                sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding         sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted         sqlite3_api->is_interrupted
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */

#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
  /* This case when the file really is being compiled as a loadable 
  ** extension */
# define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v)  sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3     \
    extern const sqlite3_api_routines *sqlite3_api;
#else
  /* This case when the file is being statically linked into the 
  ** application */
# define SQLITE_EXTENSION_INIT1     /*no-op*/
# define SQLITE_EXTENSION_INIT2(v)  (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3     /*no-op*/
#endif

#endif /* SQLITE3EXT_H */

Deleted signify/fnc-14-release.pub.

1
2


-
-
untrusted comment: fnc 0.14 public key
RWTOJ8pPCpW9YMEsLrgLmTRk0huOrEnyiLZRYo36C/9JQF/H3JnCGpFc

Added signify/fnc-16-release.pub.



1
2
+
+
untrusted comment: fnc 0.16 public key
RWQU64tpMRY9DoIKxzUWqfvtdDsNoX6wb3qBkgbJ1NQNqbJwTXsoEUkI

Changes to src/diff.c.

1
2

3
4
5
6
7
8
9
1

2
3
4
5
6
7
8
9

-
+







/*
 * Copyright (c) 2022 Mark Jamsek <mark@jamsek.com>
 * Copyright (c) 2022, 2023 Mark Jamsek <mark@jamsek.com>
 * Copyright (c) 2013-2021 Stephan Beal, the Libfossil authors and contributors.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
33
34
35
36
37
38
39

40
41
42
43
44
45
46
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







+







 */

#include <assert.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>  /* memmove() */

#include "libfossil.h"
#include "diff.h"

#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
#define MIN(_a, _b)	((_a) < (_b) ? (_a) : (_b))
#define MAX(_a, _b)	((_a) > (_b) ? (_a) : (_b))
#define starts_with(_str, _pfx) (!fsl_strncmp(_str, _pfx, sizeof(_pfx) - 1))
#define LENGTH(_ln)	((_ln)->n)  /* Length of a fsl_dline */
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
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







-
+










+
+
+
+

-
-












+




-
-
+
+







#define ANSI_RESET			ANSI_RESET_ALL
/* #define ANSI_BOLD     ";1m" */

struct diff_out_state {
	fsl_output_f	 out;		/* Output callback */
	void		*state;		/* State for this->out() */
	enum line_type	*lines;		/* Diff line type (e.g., minus, plus) */
	uint32_t	 nlines;	/* Index into this->lines */
	size_t		 nlines;	/* Index into this->lines */
	int		 rc;		/* Error reporting */
	char		 ansi;		/* ANSI colour code */
	struct hunk_scope {
		const fsl_buffer	*file;		/* Diffed file */
		char			*sig;		/* Matching function */
		char			*spec;		/* C++ specifier */
		uint32_t		 lastmatch;	/* Match line index */
		uint32_t		 lastline;	/* Last line scanned */
		fsl_size_t		 offset;	/* Match byte offset */
	} proto;
	struct diffstat {
		uint32_t add;	/* total number of added lines */
		uint32_t rm;	/* total number of removed lines */
	} diffstat;
};
static const struct diff_out_state diff_out_state_ctor =
    { NULL, NULL, NULL, 0U, 0, '\0', { NULL, NULL, NULL, 0U, 0U, 0U } };

struct sbsline {
	struct diff_out_state	*output;
	fsl_buffer		*cols[5];	/* Pointers to output columns */
	const char		*tag;		/* <span> tag */
	const char		*tag2;		/* <span> tag */
	int			 idx;		/* Write tag before idx */
	int			 end;		/* Close tag before end */
	int			 idx2;		/* Write tag2 before idx2 */
	int			 end2;		/* Close tag2 before end2 */
	int			 width;		/* Max column width in diff */
	bool			 esc;		/* Escape html characters */
	bool			 edited;	/* Line was edited in diff */
	void			*regex;		/* Colour matching lines */
};

static int		 diff_blobs(fsl_buffer const *, fsl_buffer const *,
			    fsl_output_f, void *, enum line_type **, uint32_t *,
			    /* void *regex, */ uint16_t, short, int, int **);
			    fsl_output_f, void *, enum line_type **, size_t *,
			    uint64_t *, uint16_t, short, int, int **);
static int		 fnc_output_f_diff_out(void *, void const *, fsl_size_t);
static int		 diff_outf(struct diff_out_state *, char const *, ... );
static int		 diff_out(struct diff_out_state * const, void const *,
			    fsl_int_t);
static int		 validate_scope_line(const char *);
static int		 match_hunk_function(struct hunk_scope *, fsl_int_t);
static int		 buffer_copy_lines_from(fsl_buffer *const,
164
165
166
167
168
169
170
171
172


173
174
175


176
177
178
179
180
181



182
183
184
185

186
187
188
189
190
191


192
193

194
195
196
197
198
199
200
201
202
203
204
205

206
207
208
209

210
211

212
213
214
215
216


217
218
219
220


221
222
223
224
225
226
227
168
169
170
171
172
173
174


175
176
177


178
179
180
181
182



183
184
185
186
187
188

189
190
191
192
193


194
195
196

197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212

213
214

215
216
217
218


219
220
221
222
223
224
225
226
227
228
229
230
231
232
233







-
-
+
+

-
-
+
+



-
-
-
+
+
+



-
+




-
-
+
+

-
+











-
+



-
+

-
+



-
-
+
+




+
+







static int		 sbsdiff_marker(struct sbsline *, const char *,
			    const char *);
static int		 sbsdiff_close_gap(int *);
static unsigned char	*sbsdiff_align(fsl_dline *, int, fsl_dline *, int);
static int		 sbsdiff_write_change(struct sbsline *, fsl_dline *,
			    int, fsl_dline *, int);
int
fnc_diff_text_raw(fsl_buffer const *blob1, fsl_buffer const *blob2,
    int flags, int **out)
fnc_diff_text_raw(int **out, fsl_buffer const *blob1, fsl_buffer const *blob2,
    int flags)
{
	return diff_blobs(blob1, blob2, NULL, NULL, NULL, NULL, 0, 0,
	    flags, out);
	return diff_blobs(blob1, blob2, NULL, NULL, NULL, NULL, NULL,
	    0, 0, flags, out);
}

int
fnc_diff_text_to_buffer(fsl_buffer const *blob1, fsl_buffer const *blob2,
    fsl_buffer *out, enum line_type **lines, uint32_t *nlines, short context,
    short sbswidth, int flags)
fnc_diff_text_to_buffer(fsl_buffer *out, fsl_buffer const *blob1,
    fsl_buffer const *blob2, enum line_type **lines, size_t *nlines,
    uint64_t *diffstat, short context, short sbswidth, int flags)
{
	return (blob1 && blob2 && out) ?
	    diff_blobs(blob1, blob2, fsl_output_f_buffer, out, lines,
	    nlines, context, sbswidth, flags, NULL) : FSL_RC_MISUSE;
	    nlines, diffstat, context, sbswidth, flags, NULL) : FSL_RC_MISUSE;
}

int
fnc_diff_text(fsl_buffer const *blob1, fsl_buffer const *blob2,
    fsl_output_f out, void *state, enum line_type **lines, uint32_t *nlines,
    short context, short sbswidth, int flags)
    fsl_output_f out, void *state, enum line_type **lines, size_t *nlines,
    uint64_t *diffstat, short context, short sbswidth, int flags)
{
	return diff_blobs(blob1, blob2, out, state, lines, nlines,
	return diff_blobs(blob1, blob2, out, state, lines, nlines, diffstat,
	    context, sbswidth, flags, NULL);
}

/*
 * Diff two arbitrary blobs and either stream output to the third argument
 * or return an array of copy/delete/insert triples via the final argument.
 * The third XOR final argument must be set.
 *
 * If the third argument is not NULL:
 *   state     opaque state value passed to the third when emitting output
 *   context   number of context lines (negative values fallback to default)
 *   sbswidth  sbs diff width (0 = unidiff; negative values fallback to default)
 *   sbswidth  number of columns per side (negative values fallback to default)
 *
 * If the final argument is not NULL, it is assigned a pointer to the result
 * array of copy/delete/insert triples. Ownership is transfered to the caller,
 * who must eventually dispose of it with fsl_free().
 * who must eventually dispose of it with free(3).
 *
 * Return 0 on success, any number of other codes on error.
 * Return 0 on success, nonzero on error.
 */
static int
diff_blobs(fsl_buffer const *blob1, fsl_buffer const *blob2,
    fsl_output_f out, void *state, enum line_type **lines, uint32_t *nlines,
    /* void *regex, */ uint16_t context, short sbswidth, int flags,
    fsl_output_f out, void *state, enum line_type **lines, size_t *nlines,
    uint64_t *diffstat, uint16_t context, short sbswidth, int flags,
    int **rawdata)
{
	fsl__diff_cx	c = fsl__diff_cx_empty;
	int		rc;

	*diffstat = 0;

	if (!blob1 || !blob2 || (out && rawdata) || (!out && !rawdata))
		return FSL_RC_MISUSE;

	if (context < 0)
		context = 5;
	else if (context & ~FSL__LINE_LENGTH_MASK)
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
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







-
-
-
-
-
+
+
+












-
+

-
+
+
+
+
+
+
+
+







	if (FLAG_CHK(flags, FNC_DIFF_SIDEBYSIDE)) {
		rc = max_sbs_width(&c, &flags, sbswidth, context);
		if (rc)
			goto end;
	}

	if (out) {
		/*
		 * Compute a unified or side-by-side diff.
		 * XXX Missing regex support.
		 */
		struct diff_out_state dos = diff_out_state_ctor;
		struct diff_out_state dos;

		memset(&dos, 0, sizeof(dos));

		dos.out = out;
		dos.state = state;
		if (lines && nlines) {
			dos.lines = *lines;
			dos.nlines = *nlines;
		}
		dos.ansi = !!(FLAG_CHK(flags, FNC_DIFF_ANSI_COLOR));
		if (FLAG_CHK(flags, FNC_DIFF_PROTOTYPE))
			dos.proto.file = blob1;

		if (FLAG_CHK(flags, FNC_DIFF_SIDEBYSIDE))
			rc = sbsdiff(&c, &dos, NULL /*regex*/, context, flags);
			rc = sbsdiff(&c, &dos, NULL, context, flags);
		else
			rc = unidiff(&c, &dos, NULL /*regex*/, context, flags);
			rc = unidiff(&c, &dos, NULL, context, flags);

		/*
		 * Save the total added lines to the lower 32 bits
		 * and the total removed lines to the high 32 bits.
		 */
		*diffstat = dos.diffstat.add;
		*diffstat |= (uint64_t)dos.diffstat.rm << 32;

		if (lines && nlines) {
			*lines = dos.lines;  /* realloc'd */
			*nlines = dos.nlines;
		}
		fsl_free(dos.proto.sig);
	} else if (rawdata) {
772
773
774
775
776
777
778




779
780
781
782
783
784
785
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800







+
+
+
+







		offset = hs->offset;
		--pos;
	}

	return FSL_RC_OK;
}

#define DIFF_SBSLINE_REMOVED	1
#define DIFF_SBSLINE_ADDED	2
#define DIFF_SBSLINE_UNKNOWN	3

/*
 * Render the diff triples array in cx->aEdit as a side-by-side diff in out.
 *   cx		Raw diff data
 *   out	Side-by-side diff representation
 *   regex	Show changes matching this regex
 *   context	Number of context lines
 *   flags	Flags controlling the diff
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823

824
825
826
827
828
829
830
831







-
+







	int		  nc;		/* number of c[] triples to process */
	int		  max_ci;	/* Maximum value for ci */
	int		  nleft, nright; /* Number of l and r lines to output */
	int		  ntotal;	/* Total number of lines to output */
	int		  skip;		/* Number of lines to skip */
	int		  i, j, rc = FSL_RC_OK;
	enum line_type	**lines = &dst->lines;
	uint32_t	 *nlines = &dst->nlines;
	size_t		 *nlines = &dst->nlines;
	bool		  showsep = false;

	li = ri = 0;
	memset(&s, 0, sizeof(s));
	s.output = dst;
	s.width = sbsdiff_width(flags);
	s.regex = regex;
995
996
997
998
999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009
1010
1010
1011
1012
1013
1014
1015
1016


1017
1018
1019
1020
1021
1022
1023
1024
1025







-
-
+
+







			if (!alignment) {
				rc = FSL_RC_OOM;
				goto end;
			}
			for (j = 0; nleft + nright > 0; j++) {
				char tag[30] = "<span class=\"fsl-diff-";
				switch (alignment[j]) {
				case 1:
					/* Delete one line from the left */
				case DIFF_SBSLINE_REMOVED:
					/* delete one line from the left */
					rc = sbsdiff_lineno(&s, li, SBS_LLINE);
					if (rc)
						goto end_align;
					s.idx = 0;
					fsl_strlcat(tag, "rm\">", sizeof(tag));
					s.tag = tag;
					s.end = LENGTH(&l[li]);
1022
1023
1024
1025
1026
1027
1028

1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1037
1038
1039
1040
1041
1042
1043
1044
1045


1046
1047
1048
1049
1050
1051
1052
1053
1054







+

-
-
+
+







						goto end_align;
					rc = sbsdiff_newline(&s);
					if (rc)
						goto end_align;
					assert(nleft > 0);
					nleft--;
					li++;
					++dst->diffstat.rm;
					break;
				case 2:
					/* Insert one line on the right */
				case DIFF_SBSLINE_ADDED:
					/* insert one line on the right */
					if (!s.esc) {
						rc = sbsdiff_space(&s,
						    s.width + 7, SBS_LTEXT);
						if (rc)
							goto end_align;
					}
					rc = sbsdiff_marker(&s, " > ", "&gt;");
1053
1054
1055
1056
1057
1058
1059

1060
1061
1062






1063
1064
1065
1066
1067
1068
1069
1070
1071




1072
1073
1074

1075
1076
1077
1078
1079
1080
1081
1069
1070
1071
1072
1073
1074
1075
1076
1077


1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1106







+

-
-
+
+
+
+
+
+









+
+
+
+


-
+







						    nlines, LINE_DIFF_PLUS);
						if (rc)
							goto end_align;
					}
					assert(nright > 0);
					nright--;
					ri++;
					++dst->diffstat.add;
					break;
				case 3:
					/* Left line changed into the right */
				case DIFF_SBSLINE_UNKNOWN:
					/*
					 * Most likely the left line was
					 * changed into the right but it
					 * could also be a context line.
					 */
					rc = sbsdiff_write_change(&s, &l[li],
					    li, &r[ri], ri);
					if (rc)
						goto end_align;
					assert(nleft > 0 && nright > 0);
					nleft--;
					nright--;
					li++;
					ri++;
					if (s.edited) {
						++dst->diffstat.rm;
						++dst->diffstat.add;
					}
					break;
				default:
					/* Delete left and insert right */
					/* delete left and insert right */
					rc = sbsdiff_lineno(&s, li, SBS_LLINE);
					if (rc)
						goto end_align;
					s.idx = 0;
					fsl_strlcat(tag, "rm\">", sizeof(tag));
					s.tag = tag;
					s.end = LENGTH(&l[li]);
1100
1101
1102
1103
1104
1105
1106


1107
1108
1109
1110
1111
1112
1113
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140







+
+







					rc = sbsdiff_txt(&s, &r[ri], SBS_RTEXT);
					if (rc)
						goto end_align;
					nleft--;
					nright--;
					li++;
					ri++;
					++dst->diffstat.rm;
					++dst->diffstat.add;
					break;
				}
			}
end_align:
			fsl_free(alignment);
			if (i < nc - 1) {
				ntotal = c[ci + i * 3 + 3];
1214
1215
1216
1217
1218
1219
1220
1221

1222
1223
1224
1225
1226
1227
1228
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255







-
+







	int		  ci;		/* Index into c[] */
	int		  nc;		/* number of c[] triples to process */
	int		  max_ci;	/* Maximum value for ci */
	int		  nleft, nright; /* Number of l and r lines to output */
	int		  ntotal;	/* Total number of lines to output */
	int		  skip;		/* Number of lines to skip */
	int		  i, j, rc = FSL_RC_OK;
	uint32_t	 *nlines = &dst->nlines;
	size_t		 *nlines = &dst->nlines;
	enum line_type	**lines = &dst->lines;
	bool		  html, proto, showln, showsep = false;

	proto = FLAG_CHK(flags, FNC_DIFF_PROTOTYPE);
	showln = FLAG_CHK(flags, FNC_DIFF_LINENO);
	html = FLAG_CHK(flags, FNC_DIFF_HTML);

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
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489







+
+
+




















+
+
+







		}
		li += ntotal;
		ri += ntotal;

		/* Show the differences */
		for (i = 0; i < nc; i++) {
			ntotal = c[ci + i * 3 + 1];

			dst->diffstat.rm += ntotal;

			for (j = 0; j < ntotal; j++) {
				if (lines && nlines) {
					rc = add_line_type(lines, nlines,
					    LINE_DIFF_MINUS);
					if (rc)
						return rc;
				}
				if (showln) {
					rc = unidiff_lineno(dst, li + j + 1, 0,
					    html);
					if (rc)
						return rc;
				}
				rc = unidiff_txt(dst, '-', &l[li + j],
				    html, regex);
				if (rc)
					return rc;
			}
			li += ntotal;
			ntotal = c[ci + i * 3 + 2];

			dst->diffstat.add += ntotal;

			for (j = 0; j < ntotal; j++) {
				if (lines && nlines) {
					rc = add_line_type(lines, nlines,
					    LINE_DIFF_PLUS);
					if (rc)
						return rc;
				}
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
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







-
+










+







{
	static const char	  tag_rm[] = "<span class=\"fsl-diff-rm\">";
	static const char	  tag_add[] = "<span class=\"fsl-diff-add\">";
	static const char	  tag_chg[] = "<span class=\"fsl-diff-change\">";
	const char		 *ltxt;	/* Text of the left line */
	const char		 *rtxt;	/* Text of the right line */
	enum line_type		**lines = &dst->output->lines;
	uint32_t		 *nlines = &dst->output->nlines;
	size_t			 *nlines = &dst->output->nlines;
	int	lcs[4] = {0, 0, 0, 0};	/* Bounds of common middle segment */
	int	leftsz;		/* Length of left line in bytes */
	int	rightsz;	/* Length of right line in bytes */
	int	shortest;	/* Shortest of left and right */
	int	npfx;		/* Length of common prefix */
	int	nsfx;		/* Length of common suffix */
	int	nleft;		/* leftsz - npfx - nsfx */
	int	nright;		/* rightsz - npfx - nsfx */
	int	rc = FSL_RC_OK;

	dst->edited = true;
	leftsz = left->n;
	ltxt = left->z;
	rightsz = right->n;
	rtxt = right->z;
	shortest = min(leftsz, rightsz);

	/* Count common prefix. */
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
2097
2098
2099
2100







+


















-
+
-







				    LINE_DIFF_CONTEXT);
				if (rc)
					return rc;
			}
			rc = sbsdiff_marker(dst, "   ", "");
			if (rc)
				return rc;
			dst->edited = false;
		} else {
			if (lines && nlines) {
				rc = add_line_type(lines, nlines,
				    LINE_DIFF_EDIT);
				if (rc)
					return rc;
			}
			rc = sbsdiff_marker(dst, " | ", "|");
			if (rc)
				return rc;
		}

		rc = sbsdiff_lineno(dst, rlnno, SBS_RLINE);
		if (rc)
			return rc;
		dst->idx = npfx;
		dst->end = rightsz - nsfx;
		dst->tag = tag_add;
		rc = sbsdiff_txt(dst, right, SBS_RTEXT);
		return sbsdiff_txt(dst, right, SBS_RTEXT);
		return rc;
	}

	/* A single hunk of text deleted from the left */
	if (npfx + nsfx == rightsz) {
		rc = sbsdiff_lineno(dst, llnno, SBS_LLINE);
		if (rc)
			return rc;
2081
2082
2083
2084
2085
2086
2087
2088

2089
2090
2091
2092
2093
2094
2095
2096
2115
2116
2117
2118
2119
2120
2121

2122

2123
2124
2125
2126
2127
2128
2129







-
+
-







		rc = sbsdiff_marker(dst, " | ", "|");
		if (rc)
			return rc;
		rc = sbsdiff_lineno(dst, rlnno, SBS_RLINE);
		if (rc)
			return rc;
		dst->idx = dst->end = -1;
		rc = sbsdiff_txt(dst, right, SBS_RTEXT);
		return sbsdiff_txt(dst, right, SBS_RTEXT);
		return rc;
	}

	/*
	 * At this point we know that there is a hunk of text that has
	 * changed between the left and the right. Check to see if there
	 * is a large unchanged section in the middle of that changed block.
	 */
2136
2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
2151
2169
2170
2171
2172
2173
2174
2175

2176

2177
2178
2179
2180
2181
2182
2183







-
+
-







			dst->tag = tag_add;
		} else
			dst->tag = tag_chg;
		dst->idx2 = npfx + lcs[3];
		dst->end2 = rightsz - nsfx;
		dst->tag2 = lcs[1]==nleft ? tag_add : tag_chg;
		sbsdiff_simplify_line(dst, rtxt + npfx);
		rc = sbsdiff_txt(dst, right, SBS_RTEXT);
		return sbsdiff_txt(dst, right, SBS_RTEXT);
		return rc;
	}

	/* If all else fails, show a single big change between left and right */
	rc = sbsdiff_lineno(dst, llnno, SBS_LLINE);
	if (rc)
		return rc;
	dst->idx2 = dst->end2 = 0;
2165
2166
2167
2168
2169
2170
2171
2172

2173
2174
2175
2176
2177
2178
2179
2180
2197
2198
2199
2200
2201
2202
2203

2204

2205
2206
2207
2208
2209
2210
2211







-
+
-







	rc = sbsdiff_marker(dst, " | ", "|");
	if (rc)
		return rc;
	rc = sbsdiff_lineno(dst, rlnno, SBS_RLINE);
	if (rc)
		return rc;
	dst->end = rightsz - nsfx;
	rc = sbsdiff_txt(dst, right, SBS_RTEXT);
	return sbsdiff_txt(dst, right, SBS_RTEXT);
	return rc;
}

/*
 * Add two line numbers to the beginning of a unified diff output line.
 *   dst	Output destination
 *   lln	Line number corresponding to the line in the left (old) file
 *   rln	Line number corresponding to the line in the right (new) file
2275
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2306
2307
2308
2309
2310
2311
2312

2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326







-
+













			rc = diff_out(dst, "\n", 1);
	}

	return rc;
}

int
add_line_type(enum line_type **lines, uint32_t *nlines, enum line_type type)
add_line_type(enum line_type **lines, size_t *nlines, enum line_type type)
{
	enum line_type *p;

	p = fsl_realloc(*lines, (*nlines + 1) * sizeof(enum line_type));
	if (p == NULL)
		return FSL_RC_ERROR;
	*lines = p;

	(*lines)[*nlines] = type;
	(*nlines)++;

	return FSL_RC_OK;
}

Changes to src/fnc.1.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23

24
25




26




27
28





29

30





31
32
33
34
35
36












37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83





84
85

86
87
88
89
90

91
92
93
94

95
96
97
98
99
100




101
102
103

104
105
106


107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141






142
143
144
145
146
147
148
149
150
151
152
153


154
155




156
157

158
159
160

161
162
163
164
165

166
167
168
169

170
171
172

173
174
175
176
177




178
179
180
181

182
183
184





185
186

187
188
189
190
191
192
193
194


195
196
197
198
199
200
201
202
203

204
205

206

207
208






209
210

211
212
213
214
215
216
217
218
219
220



221
222
223
224
225
226
227
228


229
230

231
232
233
234

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252







253
254
255
256
257
258
259
260
261
262
263






264
265
266

267
268


269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292




293



294


295
296
297
298
299
300
301
302





303
304
305


306
307
308
309
310
311











312
313

314
315
316

317
318
319
320
321

322
323
324





325
326
327







328
329



330
331
332
333
334
335
336

337
338

339
340
341
342

343
344
345
346
347
348
349

350
351
352
353
354


355
356


357
358

359
360
361
362
363





364
365

366
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

420
421
422
423
424


425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441

442
443

444
445
446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469


470
471
472


473

474
475


476
477

478
479
480
481
482
483

484
485

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500





501


502




503
504
505


506
507

508
509
510







511
512
513


514
515


516
517


518
519
520
521
522
523



524
525
526
527
528
529
530
531
532
533
534
535
536

537
538
539


540
541

542

543
544
545

546

547
548
549
550





551
552
553
554
555




556
557
558


559
560
561
562



563
564
565
566
567
568
569
570



















571
572

573
574

575
576
577
578

579
580


581
582
583
584
585
586
587
588









589
590
591
592
593
594
595
596

597

598
599
600
601
602

603
604


605
606




607
608
609
610

611
612
613


614
615


616
617
618
619
620




621



622


623
624
625


626
627


628
629
630
631

632
633

634
635
636
637
638
639
640
641
642
643

644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664


665
666
667

668
669

670
671
672
673
674
675






676
677
678
679
680

681
682
683

684
685
686




687
688


689
690
691
692
693
694
695


696
697


698
699

700
701
702

703
704

705

706
707

708
709

710
711
712

713
714
715
716
717
718
719

720
721

722
723
724
725
726


727

728
729
730
731




732
733


734


735

736
737
738
739




740
741


742
743

744
745

746
747

748
749

750
751

752
753

754
755



756
757

758
759
760


761

762
763
764
765
766
767
768


769
770
771
772

773
774

775
776
777




778
779
780

781
782
783

784
785


786
787
788


789
790
791
792
793
794
795
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24


25
26
27
28
29
30
31
32
33


34
35
36
37
38
39
40

41
42
43
44
45
46
47




48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66

67
68
69
70
71







72
73
74

















75
76
77

78
79


80
81
82
83
84
85

86
87
88
89
90

91


92

93
94
95




96
97
98
99
100
101

102
103


104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157


158
159
160
161
162

163
164
165

166
167
168
169
170

171
172
173
174

175
176
177

178

179



180
181
182
183
184
185
186
187
188



189
190
191
192
193
194
195
196
197
198
199
200
201
202


203
204









205
206

207
208
209


210
211
212
213
214
215


216
217
218
219
220
221
222
223



224
225
226
227
228
229
230
231
232


233
234
235
236
237
238
239
240

241

242
243
244
245
246
247
248
249
250
251
252
253
254




255
256
257
258
259
260
261
262
263
264
265
266
267
268




269
270
271
272
273
274
275


276


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298




299
300
301
302
303
304
305
306

307
308
309
310
311
312
313



314
315
316
317
318
319
320
321
322
323






324
325
326
327
328
329
330
331
332
333
334
335

336
337
338

339

340
341
342
343
344



345
346
347
348
349
350
351
352
353
354
355
356
357
358
359


360
361
362
363
364
365
366
367
368

369
370

371
372
373
374

375
376
377
378
379
380
381

382
383
384
385
386

387
388
389

390
391
392

393
394




395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423
424

425
426





















427
428
429
430
431
432
433

434
435
436
437


438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457

458
459
460
461
462
463
464
465
466

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482


483
484
485


486
487
488
489


490
491
492

493
494
495
496
497
498

499
500

501






502
503
504
505
506




507
508
509
510
511
512
513
514

515
516
517
518
519


520
521
522

523
524
525
526
527
528
529
530
531
532
533
534


535
536

537
538
539


540
541
542
543
544



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559

560
561


562
563

564
565

566
567
568
569
570

571




572
573
574
575
576
577
578



579
580
581
582



583
584
585



586
587
588
589
590
591





592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612


613
614
615


616


617
618








619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636

637
638
639
640
641

642
643

644
645
646

647
648
649
650
651
652
653

654
655


656
657


658
659
660




661
662
663
664
665
666
667
668

669
670
671


672
673


674
675




676
677

678
679









680














681
682





683
684

685

686
687

688
689
690
691



692
693
694
695
696
697
698
699
700
701

702
703
704

705
706


707
708
709
710
711

712
713
714
715
716
717
718
719

720
721
722

723
724
725

726
727
728

729
730
731
732

733
734

735
736

737

738

739

740
741
742
743
744

745
746

747




748
749
750

751
752



753
754
755
756
757

758
759
760
761
762

763
764



765
766
767
768
769

770
771
772

773
774

775
776

777
778

779
780

781
782

783
784

785
786
787
788

789
790
791
792
793
794

795
796
797
798
799
800


801
802
803
804
805

806
807

808
809


810
811
812
813
814
815

816
817
818

819
820

821
822
823


824
825
826
827
828
829
830
831
832

-
+


















-
+


+
-
-
+
+
+
+

+
+
+
+
-
-
+
+
+
+
+

+
-
+
+
+
+
+


-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+






-
+
-





-
-
-
-
-
-
-



-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-



-
+

-
-
+
+
+
+
+

-
+




-
+
-
-

-
+


-
-
-
-
+
+
+
+


-
+

-
-
+
+




-
+













-














-
-
+
+
+
+
+
+












+
+
-
-
+
+
+
+

-
+


-
+




-
+



-
+


-
+
-

-
-
-
+
+
+
+




+
-
-
-
+
+
+
+
+


+






-
-
+
+
-
-
-
-
-
-
-
-
-
+

-
+

+
-
-
+
+
+
+
+
+
-
-
+







-
-
-
+
+
+






-
-
+
+


+



-
+
-













-
-
-
-
+
+
+
+
+
+
+







-
-
-
-
+
+
+
+
+
+

-
-
+
-
-
+
+




















-
-
-
-
+
+
+
+

+
+
+
-
+
+





-
-
-
+
+
+
+
+



+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
+


-
+
-




+
-
-
-
+
+
+
+
+



+
+
+
+
+
+
+
-
-
+
+
+






-
+

-
+



-
+






-
+




-
+
+

-
+
+

-
+

-
-
-
-
+
+
+
+
+

-
+









-
+













-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







-
+



-
-
+
+
















-
+

-
+








-
+















-
-
+
+

-
-
+
+

+
-
-
+
+

-
+





-
+

-
+
-
-
-
-
-
-





-
-
-
-
+
+
+
+
+

+
+
-
+
+
+
+

-
-
+
+

-
+



+
+
+
+
+
+
+

-
-
+
+
-

+
+
-
-
+
+



-
-
-
+
+
+












-
+

-
-
+
+
-

+
-
+



+
-
+
-
-
-
-
+
+
+
+
+


-
-
-
+
+
+
+
-
-
-
+
+

-
-
-
+
+
+



-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
-
-
+


-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+








+
-
+




-
+

-
+
+

-
+
+
+
+



-
+

-
-
+
+
-
-
+
+

-
-
-
-
+
+
+
+

+
+
+
-
+
+

-
-
+
+
-
-
+
+
-
-
-
-
+

-
+

-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-


-
-
-
-
-
+
+
-

-
+

-
+



-
-
-
+
+
+
+
+
+




-
+


-
+

-
-
+
+
+
+

-
+
+






-
+
+

-
+
+

-
+


-
+


+
-
+

-
+

-
+
-

-
+
-





-
+

-
+
-
-
-
-

+
+
-
+

-
-
-
+
+
+
+

-
+
+

+
+
-
+

-
-
-
+
+
+
+

-
+
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+
+
+

-
+



+
+
-
+





-
-
+
+



-
+

-
+

-
-
+
+
+
+


-
+


-
+

-
+
+

-
-
+
+







.\"
.\" Copyright (c) 2021, 2022 Mark Jamsek <mark@jamsek.com>
.\" Copyright (c) 2021, 2022, 2023 Mark Jamsek <mark@jamsek.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt FNC 1
.Os
.Sh NAME
.Nm fnc
.Nd An interactive text-based user interface for Fossil
.Nd interactive text-based user interface for Fossil repositories
.Sh SYNOPSIS
.Nm
.Op Fl R Ar repository
.Op Ar command
.Op Fl h | -help
.Ar command
.Op Ar arg ...
.Nm
.Op Fl hv
.Nm
.Ar path
.Pp
.Nm
.Cm blame
.Op Fl h | -help
.Op Fl v | -version
.Op Fl Chr
.Op Fl c Ar commit
.Op Fl l Ar lineno
.Op Fl n Ar n
.Ar path
.Nm
.Cm branch
.Cm stash Op Po Cm get Ns | Ns Cm pop Pc Oo Ar id Oc | Fl ChPx
.Op Fl Cchopr
.Op Fl a Ar date
.Op Fl b Ar date
.Op Fl s Ar order
.Op Ar glob
.Nm
.Cm config
.Op Fl hu
.Op Fl -ls
.Op Fl R Ar path
.Op Ar setting Op Ar value
.Op Fl hl
.Op Fl u Ar option
.Op Ar option Op Ar value
.Nm
.Cm diff
.Op Fl bCDhiloPqsWw
.Op Fl x Ar n
.Op Ar artifact1 Op Ar artifact2
.Op Ar path ...
.Nm
.Cm stash
.Oo Fl ChP Oc Oo Fl x Ar n Oc Op Po Cm get Ns | Ns Cm pop Pc Oo Ar id Oc
.Nm
.Cm timeline
.Op Fl Chz
.Op Fl b Ar branch
.Op Fl c Ar commit
.Op Fl f Ar glob
.Op Fl n Ar number
.Op Fl n Ar n
.Op Fl R Ar path
.Op Fl T Ar tag
.Op Fl t Ar type
.Op Fl u Ar user
.Op Ar path
.Nm
.Cm diff
.Op Fl bChilPqsWw
.Op Fl R Ar path
.Op Fl x Ar number
.Op Ar artifact1 Op Ar artifact2
.Op Ar path ...
.Nm
.Cm tree
.Op Fl Ch
.Op Fl c Ar commit
.Op Fl R Ar path
.Op Ar path
.Nm
.Cm blame
.Op Fl Ch
.Op Fl c Ar commit Op Fl r
.Op Fl n Ar number
.Op Fl R Ar path
.Ar path
.Nm
.Cm branch
.Op Fl Cchopr
.Op Fl a Ar date | Fl b Ar date
.Op Fl R Ar path
.Op Fl s Ar order
.Op Ar glob
.Nm
.Op Ar path
.Sh DESCRIPTION
.Nm
is an interactive text-based user interface for
is an interactive text-based user interface for exploring
.Xr fossil 1
repositories,
and supports multiple views to display repository data:
repositories, and managing local changes in a Fossil work tree.
.Pp
To facilitate navigation and display repository data,
.Nm
supports multiple views:
.Bl -tag -width Ds
.It Timeline view
.It Sy Timeline
Display commits from the repository's history in chronologically
descending order.
If no
.Ar command
or
or only a
.Ar arg
are specified, or just a
.Ar path
is passed,
is specified,
.Nm
will default to displaying this view.
.It Diff view
Display changes introduced in the specified commit, or between two repository
artifacts.
.It Tree view
.It Sy Diff
Display changes introduced in the specified commit, between two repository
artifacts, or local changes in the work tree.
.It Sy Tree
Display navigable tree reflecting the repository state as at the specified
commit.
.It Blame view
.It Sy Blame
Display and annotate each line in the given file with the hyperlinked
historical commit that last modified the line.
.It Branch view
commit in which the line was last modified.
.It Sy Branch
Display navigable list of all repository branches.
.El
.Pp
.Nm
provides both global and command-specific options and runtime key
provides both global and command-specific options, and runtime key
bindings.
Global options are as follows:
.Bl -tag -width 6v
.It Fl h , -help
Display program help and usage information then exit.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm
invocation.
See command specific options for details.
.It Fl v , -version
Display program version then exit.
.El
.Pp
Global key bindings are as follows:
.Bl -tag -width Ds
.It Ic H, \&?, F1
Display runtime help.
.It Ic Tab
Switch focus between open views.
.It Ic f
Toggle the active view between fullscreen and splitscreen mode.
By default,
.Nm
will open nested views in a splitscreen if the terminal window is equal to or
greater than 110 columns wide.
will open child views in a vertical split if the terminal width is
\(>= 120 columns, otherwise a horizontal split will be used.
.It Ic G, End
Scroll to the last line in the view.
.It Ic gg, Home
Scroll to the first line in the view.
.It Ic Q
Quit
.Nm .
.It Ic q
Quit the active view.
.El
.Pp
Commands available to
.Nm
are as follows:
.Bl -tag -width 4v
.Tg conf
.Tg set
.It Xo
.It Cm config Oo Fl h | -help Oc Oo Fl -ls Oc Oo Fl R | -repo Ar path Oc \
Oo Ar setting Oo Ar value | Fl -unset Oc Oc
.Cm config
.Op Fl hl
.Op Fl u Ar option | Ar option Oo Ar value Oc
.Xc
.Dl Pq aliases: Cm conf , Cm set
Retrieve the current, or set a new,
Retrieve the current or set a new
.Ar value
for
.Ar setting
.Ar option
in the local repository.
When specified,
.Ar value
will become the new value for
.Ar setting ,
.Ar option ,
otherwise
.Nm
will display the current value of
.Ar setting .
.Ar option .
With no arguments,
.Nm Cm config
will display a list of all user-defined settings.
will list all user-defined options; see
See
.Sx ENVIRONMENT
for a detailed list of available settings
used in the display or processing of data.
When no value is defined for a given setting in the local repository,
for a detailed list of all available options and their default values.
.Pp
During initialisation,
if no value is defined for a given option in the local repository,
environment variables will be searched.
If still not found,
.Nm
will fallback to default values.
.Pp
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
Unless the global
.Fl R
option is used to specify a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
Options for
.Nm Cm config
are as follows:
.Bl -tag -width Ds
.It Fl h , -help
Display config command help and usage information then exit.
.It Fl -ls
List all available settings.
.It Fl l , -ls
List all available options.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm Cm config
invocation.
.It Fl u , -unset
.It Fl u , -unset Ar option
Clear the specified
.Ar setting .
.Ar option .
.El
.Tg save
.Tg stash
.It Cm stash Oo Po Cm get Ns | Ns Cm pop Pc Oo Ar id Oc | \
.Tg sta
.It Xo
.Cm stash
.Op Fl ChP
.Op Fl x Ar n
.Op Po Cm get Ns | Ns Cm pop Pc Oo Ar id Oc
Oo Fl C | -no-colour Oc Oo Fl h | -help Oc Oo Fl P | -no-prototype Oc \
Oo Fl x | -context Ar n Oc Oc
.Xc
.Dl Pq aliases: Cm save , Cm sta
When run with neither the
.Cm get
nor
.Cm pop
subcommands,
.Nm Cm stash
will present an interactive view of the local changes on disk and iterate
each hunk in the diff, prompting the user to either stash or keep the current
change in the checkout.
will interactively iterate over each hunk comprising the diff of local changes
in the work tree, and prompt the user to either stash or keep the current hunk.
.Pp
Valid answers are as follows:
.Bl -column -offset 2s YXZ description
.Sy b Ta scroll back Ns \(ha
.Sy m Ta show more of the current hunk Ns \(ha
.Sy y Ta yes, stash the current hunk
.Sy n Ta no, do not stash the current hunk
.Sy a Ta yes, stash this hunk and all remaining hunks in the file
.Sy k Ta no, do not stash this hunk nor any remaining hunks in the file
.Sy a Ta yes, stash this hunk and all remaining hunks in the current file
.Sy k Ta no, do not stash this hunk nor any remaining hunks in the current file
.Sy A Ta yes, stash this hunk and all remaining hunks in the diff
.Sy K Ta no, do not stash this hunk nor any remaining hunks in the diff
.Sy Q Ta abort the stash operation and discard any previous selections
.Sy \&? Ta display help dialog
.El
.Pp
\(haConditionally available when the current hunk occupies the previous
\(haConditionally available when the current hunk occupies multiple pages.
and/or following page.
.Pp
When all hunks have been selected,
.Nm
will prompt the user to enter a stash message.
If not provided, a default message of
.Qo
fnc stash HASH-PREFIX
.Qc ,
where
.Qq HASH-PREFIX
is an abbreviated SHA hash of the current checkout,
will be used.
At any time prior to the final hunk being selected
.Pq i.e., before the stash message prompt ,
the operation can be aborted by opening the help dialog and entering
.Qq Q .
This will discard all selections and leave the checkout state unchanged.
.Pq i.e., before being prompted for the stash message ,
the operation can be aborted by either answering
.Qq Q
at the prompt or opening the help dialog and entering the
.Ic Q
key binding.
This will discard any previous selections and leave the work tree unchanged.
.Pp
Available subcommands for
.Nm Cm stash
are as follows:
.Bl -tag -width 00
.It Cm get Op Ar id
.Dl Pq aliases: Cm apply
Retrieve stash
.Ar id ,
or if not provided the most recent stash entry, and apply it to the current
checkout.
Retrieve the stash changeset corresponding to the specified
.Ar id
and apply it to the current checkout.
If
.Ar id
is omitted, the most recent stash entry will be applied.
.It Cm pop Op Ar id
Remove stash
.Ar id ,
Like
or if not provided the most recent stash entry, and apply it to the current
checkout.
.Cm get ,
but also remove the changeset from the stash cache.
.El
.Pp
Options only apply to
.Nm
.Cm stash
.Po i.e., neither the
.Cm get
nor
.Cm pop
subcommands
.Pc
and are as follows:
.Bl -tag -width Ds
.It Fl C , -no-colour
Disable coloured output, which is enabled by default on supported terminals.
.It Fl h , -help
Display
.Cm stash
command help and usage information then exit.
.It Fl P , -no-prototype
Disable hunk header display of which function or scope each change is in,
which is enabled by default.
The heuristic will produce reliable results for all C-like languages
.Pq e.g., C/C++, Java, Python, JavaScript, Rust ;
Do not display the enclosing function or scope in the hunk header.
The heuristic used to determine the enclosing scope will produce reliable
results for all C-like languages
.Pq e.g., C/C++, Java, Python, JavaScript ;
however, Lisps and non-source code
.Po
e.g.,
.Xr make 1 ,
.Pq e.g., Markdown, reStructuredText
Markdown, reStructuredText
.Pc
will return meaningless results.
.It Fl x , -context Ar n
Set
.Ar n
context lines to be shown in the interactive stash diff display such that
0 \*(Le n \*(Le 64.
By default, 5 context lines are shown.
Illegal values are a no-op.
0 \*(Le
.Ar n
\*(Le 64.
Illegal values are a no-op
.Pq default: 5 .
.El
.Pp
.Tg log
.Tg tl
.It Xo
.It Cm timeline Oo Fl C | -no-colour Oc Oo Fl T | -tag Ar tag Oc \
Oo Fl b | -branch Ar branch Oc Oo Fl c | -commit Ar commit Oc \
Oo Fl f | -filter Ar glob Oc Oo Fl h | -help Oc  Oo Fl n | -limit Ar n Oc \
Oo Fl R | -repo Ar path Oc Oo Fl t | -type Ar type Oc \
Oo Fl u | -username Ar user Oc Oo Fl z | -utc Oc \
Op Ar path
.Cm timeline
.Op Fl Chz
.Op Fl b Ar branch
.Op Fl c Ar commit
.Op Fl f Ar glob
.Op Fl n Ar n
.Op Fl T Ar tag
.Op Fl t Ar type
.Op Fl u Ar user
.Op Ar path
.Xc
.Dl Pq aliases: Cm log , Cm tl
Display commit history of a repository.
Display repository history with a chronological log of all commits.
If
.Ar path
is specified, only commits that modified the file(s) at this path will populate
is specified, only show commits that modified the file(s) at this path.
the timeline.
The
.Ar path
may be absolute, relative to the current working directory, or relative to the
repository root.
.Pp
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
Unless the global
.Fl R
option is used to specify a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
If invoked in a work tree, the log entry of the commit on which the checkout
is based will be prefixed with one of the following annotations:
.Bl -column YXZ description
.It @ Ta work tree of the checked-out commit contains no local changes
.It \(a~ Ta work tree of the checked-out commit contains local changes
.El
.Pp
If no command is explicitly specified, this command will be executed by
default.
This command will be executed by default if
.Nm
is invoked without an explicit command.
.Pp
Options for
.Nm Cm timeline
are as follows:
.Bl -tag -width Ds
.It Fl b , -branch Ar branch
Display commits that are members of the specified
Display commits on the specified
.Ar branch .
The expected argument is a glob of the symbolic name of a branch, with the most
The expected argument is a glob of the symbolic branch name, with the most
recent branch to match being selected.
Pattern matching is case-insensitive unless
.Ar branch
has at least one uppercase character, in which case the search will be
has at least one uppercase character, which will make the search
case-sensitive.
By default,
.Nm
will display all commits irrespective of the branch on which they
reside.
.It Fl C , -no-colour
Disable colourised timeline, which is enabled by default on supported
Disable coloured timeline, which is enabled by default on supported
terminals.
If this option is not used, colour can be toggled with the
.Sy c
timeline view key binding as documented below.
User-defined colours are also supported, see
User-defined colours are also supported
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.It Fl c , -commit Ar commit
Open the timeline from the check-in identified by
Start timeline traversal from the specified
.Ar commit .
The expected argument is either the name of a branch, which will resolve
to the latest commit on the given branch, or (a unique abbreviated
prefix of) a valid commit SHA1 or SHA3 hash.
When this option is not supplied,
The expected argument is either a symbolic reference
.Pq e.g., branch name, tag ,
or (a unique abbreviated prefix of) a valid commit SHA1 or SHA3 hash,
or an ISO 8601 formatted date.
When this option is not used,
.Nm
will open the timeline to the latest leaf on the repository tree.
will begin traversing history from the latest commit.
For a complete list of valid arguments this option accepts, see
.Lk https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki \
"Fossil's Check-in Names".
.It Fl f , -filter Ar glob
Filter timeline by commits containing
.Ar glob
in any of the commit comment, user, or branch fields.
Pattern matching is case-insensitive unless
.Ar glob
has at least one uppercase character, in which case the search will be
has at least one uppercase character, which will make the search
case-sensitive.
Filtering can also be performed at runtime with the
.Sy F
timeline view key binding as documented below.
.It Fl h , -help
Display timeline command help and usage information then exit.
.It Fl n , -limit Ar n
Limit timeline to the
latest
.Ar n
commits.
By default,
.Nm
will load the entire history of the repository's local checkout.
will load the entire repository history.
Negative values are a no-op.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm Cm timeline
invocation.
When this option is used, the checkout-related Fossil special tags
.Qq current ,
.Qq prev ,
and
.Qq next
are invalid arguments to the
.Sy --commit
option.
When
.Sy --commit
is not specified,
.Nm
will default to populating the timeline from the latest commit.
.It Fl T , -tag Ar tag
Only display commits with T cards containing
.Ar tag .
The expected argument is a glob of a commit manifest's T card argument, with the
most recent tag to match being selected.
Pattern matching is case-insensitive unless
.Ar tag
has at least one uppercase character, in which case the search will be
has at least one uppercase character, which will make the search
case-sensitive.
By default,
.Nm
will indiscriminately display all commits irrespective of which T cards
are attached to the commit manifest.
will display all commits irrespective of which T cards are attached
to the commit manifest.
.It Fl t , -type Ar type
Only display
.Ar type
commits.
Valid
.Ar type
values are as follows:
.Bl -column -offset 2s YXZ description
.Sy ci Ta check-in
.Sy w Ta wiki
.Sy t Ta ticket
.Sy e Ta technote
.Sy f Ta forum post
.Sy g Ta tag artifact
.El
.Pp
By default, when this option is not supplied,
By default,
.Nm
will indiscriminately load all commits irrespective of
will load all commits irrespective of
.Ar type .
This is a repeatable flag
.Pq e.g., Nm Cm timeline Cm -t e -t t .
.It Fl u , -username Ar user
Only display commits authored by
.Ar user .
The search is case-insensitive by default unless
.Ar user
contains at least one uppercase character, in which case the search will be
contains at least one uppercase character, which will make the search
case-sensitive.
.It Fl z , -utc
Use Coordinated Universal Time (UTC) rather than local time when
displaying commit dates and timestamps.
.El
.Pp
Key bindings for
.Nm Cm timeline
are as follows:
.Bl -tag -width Ds
.It Ic Arrow-down, j, >, \&.
Move selection cursor down the timeline.
.It Ic Arrow-up, k, <, \&,
Move selection cursor up the timeline.
.It Ic Arrow-right, l
Scroll the view two columns to the right in the buffer.
The comment field moves left on the screen.
Scroll view to the right in the buffer.
Comment field contents move left on the screen.
.It Ic Arrow-left, h
Scroll the view two columns to the left in the buffer.
The comment field moves right on the screen.
Scroll view to the left in the buffer.
Comment field contents move right on the screen.
.It Ic $
Scroll view to the rightmost position.
Scroll the view right to the end of the longest comment summary line on the
page.
This corresponds to the end of the longest log message summary line
on the page.
.It Ic 0
Scroll the view left to the beginning of the line.
Scroll view left to the start of the line.
.It Ic C-f, Page-down
Scroll timeline view one page downwards in the buffer.
.It Ic C-b, Page-up
Scroll timeline view one page upwards in the buffer.
.It Ic C-d
Scroll timeline view half a page downwards in the buffer.
Scroll timeline view half of one page downwards in the buffer.
.It Ic C-u
Scroll timeline view half a page upwards in the buffer.
Scroll timeline view half of one page upwards in the buffer.
.It Ic G, End
Move selection cursor to the last commit on the timeline (i.e., oldest commit
in the repository).
.It Ic gg, Home
Move selection cursor to the first commit on the timeline (i.e., newest commit
in the repository).
.It Ic Enter
Open a
.Cm diff
view displaying the changeset of the currently selected commit.
.It Ic Space
(Un)tag the currently selected commit as the base commit for the next tagged
commit to be diffed against.
If another commit is already tagged, show the changes between it and the
selected commit.
Tag or untag the currently selected commit as the base commit
for the next tagged commit to be diffed against.
If another commit is already tagged, open a
.Cm diff
view showing the changes between it and the currently selected commit.
.It Ic b
Open and populate a
.Cm branch
Open and populate branch view with all repository branches.
view with all repository branches.
One of the listed branches can be selected to display a new
.Cm timeline
view of its commit history.
.It Ic C
Diff local changes on disk in the current checkout against the selected
commit.
Diff local changes on disk in the current work tree against the currently
selected commit.
.It Ic c
Toggle colourised timeline.
Toggle coloured timeline.
On supported terminals,
.Nm
will default to displaying the timeline in colour.
Colours can be customised using the
.Cm config
command or environment variables
.Po see
.Sx ENVIRONMENT
for details
.Pc .
.It Ic F
Prompt to enter a search term to filter a new timeline view by commits with
comment, user, or branch fields that match the entered pattern.
Prompt to enter a search term to filter a new timeline view that displays
commits with comment, user, or branch fields that match the entered pattern.
If no commits match, a message is displayed on screen.
.It Ic t
Open a
.Cm tree
Display the tree of the repository corresponding to the currently selected
commit.
view displaying the tree of the repository corresponding
to the currently selected commit.
.It Ic /
Prompt to enter a search term to begin searching for commits matching
the pattern provided.
The search term is an extended regular expression, which is cross-referenced
against a commit's comment, the username of its author, branch, and SHA1
or SHA3 hash.
The search term is an extended regular expression that is matched against the
comment, author username, branch, and SHA1 or SHA3 hash of each commit in the
repository.
See
.Xr re_format 7
for regular expression syntax.
.It Ic n
Find the next commit that matches the current search term.
The search will continue until either a match is found or the earliest commit
on the timeline is consumed.
.It Ic N
Find the previous commit that matches the current search term.
The search will continue until either a match is found or the latest commit
on the timeline is consumed.
.It Ic Backspace
Cancel the current search or timeline traversal
Cancel the current search or timeline traversal in progress
.Po
i.e.,
.Sy / ,
i.e., operations executed with
.Ic /
.Sy G ,
or
.Ic G Ns / Ns
.Sy End
.Ic End
.Pc .
.El
.Tg di
.It Xo
.It Cm diff Oo Fl b | -brief Oc Oo Fl C | -no-colour Oc Oo Fl h | -help Oc \
.Cm diff
Oo Fl i | -invert Oc Oo Fl l | -line-numbers Oc Oo Fl P | -no-prototype Oc \
Oo Fl q | -quiet Oc Oo Fl R | -repo Ar path Oc Oo Fl s | -sbs Oc \
Oo Fl W | -whitespace-eol Oc Oo Fl w | -whitespace Oc \
Oo Fl x | -context Ar n Oc Oo Ar artifact1 Oo Ar artifact2 Oc Oc Op Ar path ...
.Op Fl bCDhiloPqsWw
.Op Fl x Ar n
.Op Ar artifact1 Op Ar artifact2
.Op Ar path ...
.Xc
.Dl Pq alias: Cm di
Display the differences between two repository artifacts, or between the local
changes on disk and a given commit.
If neither
.Ar artifact1
changes in the work tree and a given commit.
.Pp
If invoked in a work tree with no
.Ar artifact
nor
.Ar artifact2
are specified,
arguments
specified,
.Nm
will diff the local changes on disk against the version on which the current
checkout is based.
If only
will show the differences between the local changes in the work tree and
the commit on which the current checkout is based.
If invoked in a work tree and only
.Ar artifact1
is specified,
.Nm
will diff the current checkout, including any local changes on disk, against
this version.
When both arguments are specified, the changes between these two versions will
be displayed.
If supplied,
will show the differences between the local changes in the work tree and the
commit referenced by
.Ar artifact1 .
When
.Ar artifact1
and
.Ar artifact2
are specified, the differences between
these two versions will be displayed.
Both artifact arguments must resolve to the same type
.Pq i.e., commits or blobs ,
and are expected to be either: symbolic references
.Pq e.g., branch names, tags ;
a commit or blob SHA1 or SHA3
.Pq unique abbreviated
hash; or an ISO 8601 formatted date.
If one or more
.Ar path
arguments are supplied,
.Nm
will filter diffs between commits by
will filter diffs
.Ar path
so that only changes involving the file(s) identified are displayed.
so that only changes involving the file(s) in the named paths are displayed.
Paths may be absolute, relative to the current working directory, or relative
to the repository root.
Both
.Ar artifact1
.Pp
and
.Ar artifact2
When invoked outside a work tree with the global
.Fl R
must be of the same type, which is expected to be either a symbolic check-in
name, tag, (unique abbreviated prefix of) a commit or blob artifact SHA1
or SHA3 hash, or an ISO 8601 formatted date.
Both artifact arguments must be supplied when diffing blobs; any following
non-option arguments are invalid and will be ignored.
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
option or requesting the differences between blobs, both artifact arguments
must be specified; in the latter case, any trailing arguments are invalid
and will be ignored.
.Pp
Unless the global
.Fl R
option is used to specify a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
Options for
.Nm Cm diff
are as follows:
.Bl -tag -width Ds
.It Fl b , -brief
Omit all changes.
Display file index and hash lines only.
Show the file index and hash lines only.
.It Fl C , -no-colour
Disable coloured diff output, which is enabled by default on supported
terminals.
If this option is not used, colour can be toggled with the
.Sy c
.Ic c
diff view key binding as documented below.
User-defined colours are also supported, see
User-defined colours are also supported
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.It Fl D , -min-diffstat
Show minimal diffstat instead of the more verbose plot bar histogram.
.It Fl h , -help
Display diff command help and usage information then exit.
.It Fl i , -invert
Invert the difference between artifacts when displaying the diff.
Invert the differences between artifacts.
.It Fl l , -line-numbers
Display file line numbers in diff output.
As documented below, this option can be toggled with the
Display actual file line numbers in diff output.
.It Fl o , -no-curses
.Sy L
diff view key binding.
Do not initialise curses to render the diff view.
Write the diff directly to the standard output.
.It Fl P , -no-prototype
Disable hunk header display of which function or scope each change is in,
which is enabled by default.
The heuristic will produce reliable results for all C-like languages
.Pq e.g., C/C++, Java, Python, JavaScript, Rust ;
Do not display the enclosing function or scope in the hunk header.
The heuristic used to determine the enclosing scope will produce reliable
results for all C-like languages
.Pq e.g., C/C++, Java, Python, JavaScript ;
however, Lisps and non-source code
.Po
e.g.,
.Xr make 1 ,
.Pq e.g., Markdown, reStructuredText
Markdown, reStructuredText
.Pc
will return meaningless results.
Function prototype cannot be displayed in the hunk header with either
.Fl l|-line-numbers
This option is mutually exclusive with
.Fl l
or
.Fl s|-sbs
and
.Fl s ,
formatted diffs.
This option can be toggled at runtime with the
.Sy p
key binding as documented below.
which produce incompatible hunk headers.
.It Fl q , -quiet
Disable verbose output; that is, do not output complete content of newly added
Do not output complete content of newly added
or deleted files, which are displayed by default.
Verbosity can also be toggled with the
.Sy v
key binding as documented below.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
Only show the file index and hash lines.
.Nm Cm diff
invocation.
When this option is used, both
.Ar artifact1
and
.Ar artifact2
are required, and the checkout-related Fossil special tags
.Qq current ,
.Qq prev ,
and
.Qq next
are invalid
.Sy artifact
operands.
.It Fl s , -sbs
Display a side-by-side formatted diff.
As documented below, this option can also be toggled at runtime with the
.Sy S
key binding.
.Po Mutually exclusive with
.Fl l , -line-numbers
This option is mutually exclusive with
.Fl l .
.Pc
.It Fl W , -whitespace-eol
Ignore end-of-line whitespace-only changes when displaying the diff.
Ignore end-of-line whitespace-only changes.
.It Fl w , -whitespace
Ignore whitespace-only changes when displaying the diff.
Ignore whitespace-only changes.
.It Fl x , -context Ar n
Set
.Ar n
context lines to be shown in the diff such that 0 \*(Le n \*(Le 64.
By default, 5 context lines are shown.
Illegal values are a no-op.
context lines to be shown in the diff such that
0 \*(Le
.Ar n
\*(Le 64.
Illegal values are a no-op
.Pq default: 5 .
.El
.Pp
All the above options
.Po
sans
except
.Fl h
and
.Fl R
.Fl o
.Pc
can be made persistent as global or per-repo settings.
See
can be made persistent as global or repository options via the
.Ev FNC_DIFF_FLAGS
option
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.Pp
Key bindings for
.Nm Cm diff
are as follows:
.Bl -tag -width Ds
.It Ic Arrow-down, j
Move the selection cursor down one line.
Scroll view one line downwards in the buffer.
Diff output moves upwards on the screen.
.It Ic Arrow-up, k
Move the selection cursor up one line.
Scroll view one line upwards in the buffer.
Diff output moves downwards on the screen.
.It Ic Arrow-right, l
Scroll the view two columns to the right in the buffer.
Scroll view to the right in the buffer.
Diff output moves left on the screen.
.It Ic Arrow-left, h
Scroll the view two columns to the left in the buffer.
Scroll view to the left in the buffer.
Diff output moves right on the screen.
.It Ic $
Scroll view to the rightmost position.
Scroll the view right to the end of the longest line in the diff.
This corresponds to the end of the longest line on the page.
.It Ic 0
Scroll the view left to the beginning of the line.
Scroll view left to the start of the line.
.It Ic C-e
Scroll view one line downwards in the buffer.
Move the selection cursor down one line.
Diff output moves upwards on the screen.
.It Ic C-y
Scroll view one line upwards in the buffer.
Move the selection cursor up one line.
Diff output moves downwards on the screen.
.It Ic C-f, Page-down, Space
Scroll diff view one page downwards in the buffer.
.It Ic C-b, Page-up
Scroll diff view one page upwards in the buffer.
.It Ic C-d
Scroll diff view half a page downwards in the buffer.
Scroll diff view half of one page downwards in the buffer.
.It Ic C-u
Scroll diff view half a page upwards in the buffer.
Scroll diff view half of one page upwards in the buffer.
.It Ic G, End
Scroll to the end of the view (i.e., last line of diff output).
.It Ic gg, Home
Scroll to the top of the view (i.e., first line of diff output).
.It Ic C-k, K, <, \&,
If the
.Cm diff
If the diff is derived from a
view is derived from the
.Cm timeline
view, move up the timeline
to the previous (i.e., newer) commit and display its diff.
If the diff is derived from a
view, move up to the previous
.Pq i.e., newer
commit and display its diff.
If derived from the
.Cm blame
view, display the commit diff of the previous line in the annotated file.
view, move up to the previous line in the annotated file and display the
corresponding diff.
.It Ic C-j, J, >, \&.
If the
.Cm diff
If the diff is derived from a
view is derived from the
.Cm timeline
view, move down the timeline
to the next (i.e., older) commit and display its diff.
If the diff is derived from a
view, move down the timeline to the next
.Pq i.e., older
commit and display its diff.
If derived from the
.Cm blame
view, display the commit diff of the next line in the annotated file.
view, move down to the next line in the annotated file and display the
corresponding diff.
.It Ic C-p
Navigate to previous file in the diff.
Navigate to the previous file in the diff.
.It Ic C-n
Navigate to next file in the diff.
Navigate to the next file in the diff.
.It Ic \&[
Navigate to previous hunk in the diff.
Navigate to the previous hunk in the diff.
.It Ic \&]
Navigate to next hunk in the diff.
Navigate to the next hunk in the diff.
.It Ic \&-, \&_
Decrease the number of context lines shown in diff output.
Decrease the number of context lines in the diff.
.It Ic \&=, \&+
Increase the number of context lines shown in diff output.
Increase the number of context lines in the diff.
.It Ic #
Toggle display of diff view line numbers.
Toggle the display of diff view
.Pq not actual file
line numbers.
.It Ic @
Open prompt to enter line number and navigate to that line in the view.
Open prompt to enter a line number and navigate to that line in the view.
.It Ic b
Toggle brief diff mode by only displaying file index and hash lines.
.It Ic B
Open and populate the
.Cm branch
Open and populate branch view with all repository branches.
view with all repository branches.
.It Ic c
Toggle coloured diff output.
On supported terminals,
.Nm
will default to displaying changes and diff metadata in colour.
.It Ic F
Open prompt to enter file number and navigate to that file in the diff.
.It Ic D
Toggle between minimal and histogram diffstat.
.It Ic i
Toggle inversion of diff output.
.It Ic L
Toggle display of file line numbers in the diff.
Toggle file line number formatted diff.
.It Ic P
Write the currently viewed diff to a patch file.
Write the currently viewed diff to a file on disk.
.Nm
will prompt the user for a file path, which must be absolute or relative to
the current working directory.
will prompt the user for a path, which can be absolute or relative, that
points to a location in either the current work tree or the
.Pa tmp
directory.
If no path is input and the
.Sy return
key is entered, the patch will be written to the current working directory
key is entered, the diff will be written to the current working directory
using the first ten characters of the current artifact hash as the filename
with a
.Sy .patch
.Qq .diff
extension
.Pq e.g., Qq Pa 2870235eef.patch .
.Pq e.g., Pa 2870235eef.diff .
If the path already exists, it will be overwritten.
.It Ic p
In the diff hunk header, toggle display of which function each change is in;
for example:
In the diff hunk header, toggle display of which function or scope
each change is in; for example:
.Sy @@ -2360,10 +2361,11 @@ draw_commits(struct fnc_view *view)
.It Ic S
Toggle display of a side-by-side formatted diff.
.It Ic v
Toggle verbosity of diff output.
By default,
.Nm
807
808
809
810
811
812
813




814
815



816
817


818
819
820


821
822
823
824
825
826

827
828
829





830
831
832
833
834


835
836
837
838
839
840
841
842
843



844
845
846
847
848
849
850
851
852
853
854


855
856


857
858
859

860
861
862
863







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
844
845
846
847
848
849
850
851
852
853
854


855
856
857
858

859
860
861
862

863
864
865
866
867
868
869
870
871



872
873
874
875
876
877
878
879


880
881
882
883
884
885
886
887
888


889
890
891
892
893
894
895
896
897
898
899
900
901

902
903
904

905
906
907


908
909



910
911
912
913
914
915
916
917
918
919
920
921
















922
923
924
925
926
927
928







+
+
+
+
-
-
+
+
+

-
+
+


-
+
+






+
-
-
-
+
+
+
+
+



-
-
+
+







-
-
+
+
+










-
+
+

-
+
+

-
-
+

-
-
-
+
+
+
+
+
+
+





-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







.Xr re_format 7 .
.It Ic n
Find the next line that matches the current search term.
.It Ic N
Find the previous line that matches the current search term.
.El
.Tg dir
.Tg tr
.It Xo
.Cm tree
.Op Fl Ch
.It Cm tree Oo Fl C | -no-colour Oc Oo Fl c | -commit Ar commit Oc \
Oo Fl h | -help Oc Oo Fl R | -repo Ar path Oc Op Ar path
.Op Fl c Ar commit
.Op Ar path
.Xc
.Dl Pq aliases: Cm dir , Cm tr
Display navigable, hierarchical tree of a repository.
Display a navigable tree of the repository.
.Pp
If a
.Ar path
is specified, display tree nodes of this path.
is specified, display the corresponding subtree, otherwise display the root
of the tree.
The
.Ar path
may be absolute, relative to the current working directory, or relative to the
repository root.
With no options passed, the tree will reflect the state of the latest commit on
trunk.
.Pp
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
Unless the global
.Fl R
option is used to specify a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
Tree nodes are lexicographically ordered and may be postfixed with an identifier
corresponding to the mode of the file object on disk as returned by
Tree nodes are lexicographically ordered and may be postfixed with an
identifier corresponding to the mode of the file object on disk as returned by
.Xr lstat 2 :
.Bl -column -offset Ds YXZ description
.It / Ta directory
.It * Ta executable
.It @ Ta symbolic link
.El
.Pp
Nodes representing symbolic links are also annotated with the path of the
source file.
Nodes representing symbolic links are further annotated with the path of the
source file
.Pq e.g., symlink@  ->  targetpath
.Pp
Options for
.Nm Cm tree
are as follows:
.Bl -tag -width Ds
.It Fl C , -no-colour
Disable coloured output, which is enabled by default on supported terminals.
If this option is not used, colour can be toggled with the
.Sy c
tree view key binding as documented below.
User-defined colours are also supported, see
User-defined colours are also supported
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.It Fl c , -commit Ar commit
The displayed tree will reflect the state of the repository as at the check-in
identified by
Display the repository tree corresponding to the checkin identified by
.Ar commit .
The expected argument is either the name of a branch, which will resolve
to the latest commit on the given branch, or (a unique abbreviated
prefix of) a valid commit SHA1 or SHA3 hash.
The expected argument is either a symbolic reference
.Pq e.g., branch name, tag ,
or (a unique abbreviated prefix of) a valid commit SHA1 or SHA3 hash,
or an ISO 8601 formatted date.
When this option is not used,
.Nm
will display the tree of the latest commit.
For a complete list of valid arguments this option accepts, see
.Lk https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki \
"Fossil's Check-in Names".
.It Fl h , -help
Display tree command help and usage information then exit.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm Cm tree
invocation.
When this option is used, the checkout-related Fossil special tags
.Qq current ,
.Qq prev ,
and
.Qq next
are invalid arguments to the
.Sy --commit
option.
.El
.Pp
Key bindings for
.Nm Cm tree
are as follows:
.Bl -tag -width Ds
.It Ic Enter, Arrow-right, l
900
901
902
903
904
905
906
907

908
909

910
911
912
913
914
915

916
917
918
919
920
921
922

923
924

925
926

927
928
929
930



931
932
933


934
935
936
937
938
939
940
941
942


943
944
945







946
947

948
949
950
951
952
953








954
955
956
957
958
959
960
961
962
963
964
965
966


967
968


969
970
971
972

973
974
975
976
977





978
979

980
981
982
983
984
985
986

987
988
989
990
991
992
993
994
995
996
997
998

999
1000
1001
1002
1003


1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029



1030
1031
1032


1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045


1046
1047
1048


1049

1050

1051
1052
1053
1054
1055
1056
1057
1058

1059
1060

1061
1062
1063
1064
1065
1066

1067
1068

1069
1070
1071
1072

1073
1074

1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086


1087

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097

1098

1099
1100



1101
1102
1103





1104

1105
1106
1107
1108
1109
1110

1111

1112
1113
1114





1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165


1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
937
938
939
940
941
942
943

944
945

946
947
948
949
950
951

952
953
954
955
956
957
958

959
960

961
962

963
964



965
966
967
968


969
970
971
972
973
974
975
976
977
978
979
980
981



982
983
984
985
986
987
988
989

990
991





992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014

1015
1016
1017



1018
1019




1020
1021
1022
1023
1024
1025

1026
1027
1028
1029
1030
1031
1032

1033
1034



1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045


1046
1047
1048





















1049



1050
1051
1052



1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065


1066
1067
1068


1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
1080

1081
1082

1083
1084
1085
1086
1087
1088

1089
1090

1091
1092
1093
1094

1095
1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125


1126
1127
1128



1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

1141
1142
1143



1144
1145
1146
1147
1148
1149
1150
1151
1152
1153

1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172

1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212








1213
1214
1215
1216
1217
1218
1219







-
+

-
+





-
+






-
+

-
+

-
+

-
-
-
+
+
+

-
-
+
+









+
+
-
-
-
+
+
+
+
+
+
+

-
+

-
-
-
-
-
+
+
+
+
+
+
+
+












-
+
+

-
+
+

-
-
-
+

-
-
-
-
+
+
+
+
+

-
+






-
+

-
-
-







-
+



-
-
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

-
-
-
+
+
+
-
-
-
+
+











-
-
+
+

-
-
+
+

+
-
+







-
+

-
+





-
+

-
+



-
+

-
+












+
+
-
+










+

+
-
-
+
+
+
-
-
-
+
+
+
+
+

+





-
+

+
-
-
-
+
+
+
+
+





-
+


















-
+











-
+













-
+
+

-
+
+









-
-
-
-
-
-
-
-







.It Ic Arrow-up, k
Move selection cursor one node up the tree.
.It Ic C-f, Page-down
Scroll tree view one page downwards in the buffer.
.It Ic C-b, Page-up
Scroll tree view one page upwards in the buffer.
.It Ic C-d
Scroll tree view half a page downwards in the buffer.
Scroll tree view half of one page downwards in the buffer.
.It Ic C-u
Scroll tree view half a page upwards in the buffer.
Scroll tree view half of one page upwards in the buffer.
.It Ic Home, gg
Move selection cursor to the first node in the tree.
.It Ic End, G
Move selection cursor to the last node in the tree.
.It Ic b
Open and populate branch view with all repository branches.
Open and populate the branch view with all repository branches.
.It Ic c
Toggle coloured output.
On supported terminals,
.Nm
will default to displaying the tree in colour.
.It Ic d
Toggle ISO8601 modified timestamp display for each tree entry.
Toggle display of the last modified timestamp for each tree entry.
.It Ic i
Toggle SHA hash display for all file nodes displayed in the tree.
Toggle display of the hash ID for all file nodes in the tree.
.It Ic t
Open
Open the
.Cm timeline
view for the currently selected tree node.
This will display the timeline of all commits that involve the versioned
file(s) corresponding to the selected node.
view of the currently selected tree entry.
This will display the log of all commits involving the tracked
file(s) corresponding to the selected tree node.
.It Ic /
Prompt to enter a search term to begin searching the tree for nodes matching the
entered pattern.
Prompt to enter a search term to begin searching the tree for entries
matching the entered pattern.
The search term is an extended regular expression, as documented in
.Xr re_format 7 ,
and is matched against the path of each tree node.
.It Ic n
Find the next tree node that matches the current search pattern.
.It Ic N
Find the previous tree node that matches the current search pattern.
.El
.Tg praise
.Tg bl
.It Xo
.It Cm blame Oo Fl C | -no-colour Oc \
Oo Fl c | -commit Ar commit Oo Fl r | -reverse Oc Oc Oo Fl h | -help Oc \
Oo Fl n | -limit Ar n Oc Oo Fl R | -repo Ar path Oc Ar path
.Cm blame
.Op Fl Chr
.Op Fl c Ar commit
.Op Fl l Ar lineno
.Op Fl n Ar n
.Ar path
.Xc
.Dl Pq aliases: Cm praise , Cm bl
Show commit attribution history for each line of the file at the specified
Show commit attribution history for each line of the file at the named
.Ar path ,
which may be absolute, relative to the current working directory, or relative to
the repository root.
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
which may be absolute, relative to the current working directory,
or relative to the repository root.
.Pp
Unless the global
.Fl R
option is used to specifiy a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
Options for
.Nm Cm blame
are as follows:
.Bl -tag -width Ds
.It Fl C , -no-colour
Disable coloured output, which is enabled by default on supported terminals.
If this option is not used, colour can be toggled with the
.Sy c
blame view key binding as documented below.
User-defined colours are also supported, see
User-defined colours are also supported
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.It Fl c , -commit Ar commit
Start blame of file at the specified
.Ar path
from the check-in identified by
Start annotation of the tracked file from the specified
.Ar commit .
The expected argument is either the name of a branch, which will resolve
to the latest commit on the given branch, or (a unique abbreviated
prefix of) a valid commit SHA1 or SHA3 hash.
When this option is not supplied,
The expected argument is either a symbolic reference
.Pq e.g., branch name, tag ,
or (a unique abbreviated prefix of) a valid commit SHA1 or SHA3 hash,
or an ISO 8601 formatted date.
When this option is not used,
.Nm
will blame the version of the file from the current checkout.
will begin annotation from the latest commit.
For a complete list of valid arguments this option accepts, see
.Lk https://fossil-scm.org/home/doc/trunk/www/checkin_names.wiki \
"Fossil's Check-in Names".
.It Fl h , -help
Display blame command help and usage information then exit.
.It Fl l , -line Ar lineno
Open annotated file at
Open the annotated file and navigate directly to
.Ar lineno .
As documented below, once the file is loaded, the
.Sy @
key binding can be used to navigate to an arbitrary line in the file.
.It Fl n , -limit Ar n
Limit depth of blame history to
.Ar n
commits or seconds.
The latter is denoted by a postfixed 's' (e.g., 30s).
With this option,
.Nm
will traverse either as many commits as specified, or as possible in the
will traverse either as many commits as specified or as possible in the
specified time limit.
By default,
.Nm
will traverse the entire historical record of the file, which can be expensive
for large files that span many commits.
will traverse the entire historical record of the file,
which can be expensive for large files that span many commits.
Use this option for a faster, more targeted annotation.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm Cm blame
invocation.
When this option is used, the checkout-related Fossil special tags
.Qq current ,
.Qq prev ,
and
.Qq next
are invalid arguments to the
.Sy --commit
option.
When
.Sy --commit
is not specified,
.Nm
will default to blaming the version of the file found in the latest commit.
.It Fl r , -reverse
Reverse annotate the file starting from a historical commit and move forward in
time.
That is, rather than show the most recent change to each line, show the first
Reverse annotate the file starting from a historical commit and move forward
in time so that instead of showing the most recent commit that changed each
line, show the first commit that modified each line after the specified
time each line was modified by a subsequent commit after the specified
.Ar commit .
(Requires \fB\-c\fP|\fB\-\-commit\fP.)
.Ar commit
.Pq requires Fl c .
.El
.Pp
Key bindings for
.Nm Cm blame
are as follows:
.Bl -tag -width Ds
.It Ic Arrow-down, j
Move selection cursor down one line.
.It Ic Arrow-up, k
Move selection cursor up one line.
.It Ic Arrow-right, l
Scroll the view two columns to the right in the buffer.
File output moves left on the screen.
Scroll view to the right in the buffer.
File contents move left on the screen.
.It Ic Arrow-left, h
Scroll the view two columns to the left in the buffer.
File output moves right on the screen.
Scroll view to the left in the buffer.
File contents move right on the screen.
.It Ic $
Scroll view to the rightmost position.
Scroll the view right to the end of the longest line in the file.
This corresponds to the end of the longest line on the page.
.It Ic 0
Scroll the view left to the beginning of the line.
.It Ic C-f, Page-down
Scroll blame view one page downwards in the buffer.
.It Ic C-b, Page-up
Scroll blame view one page upwards in the buffer.
.It Ic C-d
Scroll blame view half a page downwards in the buffer.
Scroll blame view half of one page downwards in the buffer.
.It Ic C-u
Scroll blame view half a page upwards in the buffer.
Scroll blame view half of one page upwards in the buffer.
.It Ic Home, gg
Move selection cursor to the first line in the file.
.It Ic End, G
Move selection cursor to the last line in the file.
.It Ic Enter
Display the
Open a
.Cm diff
of the commit corresponding to the currently selected line.
view of the commit corresponding to the currently selected line.
.It Ic #
Toggle display of file line numbers.
.It Ic @
Open prompt to enter line number and navigate to that line in the file.
Open prompt to enter a line number and navigate to that line in the file.
.It Ic B, Backspace
Reload the previous blamed version of the file.
Reload the previously blamed version of the file.
.It Ic b
Blame the version of the file corresponding to the commit in the currently
selected line.
.It Ic c
Toggle coloured output.
On supported terminals,
.Nm
will default to displaying the blamed file in colour.
.It Ic p
Blame the version of the file corresponding to the parent of the commit in
the currently selected line.
.It Ic T
Open and populate a
.Cm branch
Open and populate branch view with all repository branches.
view with all repository branches.
.It Ic /
Prompt to enter a search term to begin searching the file for tokens matching
the entered pattern.
The search term is an extended regular expression, as documented in
.Xr re_format 7 .
.It Ic N
Find the previous token that matches the current search pattern.
.It Ic n
Find the next token that matches the current search pattern.
.El
.Tg br
.Tg tag
.It Xo
.It Cm branch Oo Fl C | -no-colour Oc Oo Fl -after Ar date | \
Fl -before Ar date Oc Oo Fl h | -help Oc Oo Fl -open | Fl -closed Oc \
.Cm branch
.Op Fl Cchopr
.Op Fl a Ar date
Oo Fl p | -no-private Oc Oo Fl R | -repo Ar path Oc Oo Fl r | -reverse Oc \
Oo Fl s | -sort Ar order Oc Op Ar glob
.Dl Pq aliases: Cm tag , Cm br
.Op Fl b Ar date
.Op Fl s Ar order
.Op Ar glob
.Xc
.Dl Pq aliases: Cm br , Cm ref
Display navigable list of repository branches.
.Pp
If
.Ar glob
is specified, only display branches matching the pattern provided.
Pattern matching is case-insensitive unless
.Ar glob
contains at least one uppercase character, in which case the search will be
contains at least one uppercase character, which will make the search
case-sensitive.
.Pp
Unless the
.Sy --repo
option is used, this command must be invoked from within a work tree; that is,
Unless the global
.Fl R
option is used to specify a
.Xr fossil 1
repository, this command must be invoked from within a work tree; that is,
.Nm
assumes a local checkout is open in or above the current working directory.
.Pp
Branches are lexicographically ordered by default, and are prefixed with an
identifier corresponding to the branch state (i.e., open/closed).
The current and private branches are additionally annotated with a postfixed
The current and private branches are further annotated with a postfixed
identifier:
.Bl -column -offset Ds ABCDEFGHIJ description
.It +dev-foo Ta open
.It -rm-bar Ta closed
.It +trunk@ Ta current
.It +wip-baz* Ta private
.El
.Pp
All branches, irrespective of state or privacy, are displayed by default, but
can be filtered based on several characteristics.
.Pp
Options for
.Nm Cm branch
are as follows:
.Bl -tag -width Ds
.It Fl a , -after Ar date
Display only those branches with activity after the specified
.Ar date ,
which is expected to be either an ISO8601
which is expected to be either an ISO 8601
.Po e.g.,
.Sy 2020-10-10
.Pc
or unambiguous
.Sy DD/MM/YYYY
or
.Sy MM/DD/YYYY
formatted date.
.It Fl b , -before Ar date
Display only those branches with activity before the specified
.Ar date ,
which is expected to be either an ISO8601
which is expected to be either an ISO 8601
.Po e.g.,
.Sy 2020-10-10
.Pc
or unambiguous
.Sy DD/MM/YYYY
or
.Sy MM/DD/YYYY
formatted date.
.It Fl C , -no-colour
Disable coloured output, which is enabled by default on supported terminals.
If this option is not used, colour can be toggled with the
.Sy c
branch view key binding as documented below.
User-defined colours are also supported, see
User-defined colours are also supported
.Po see
.Sx ENVIRONMENT
for details.
for details
.Pc .
.It Fl c , -closed
Display only closed branches.
.It Fl h , -help
Display branch command help and usage information then exit.
.It Fl o , -open
Display only opened branches.
.It Fl p , -no-private
Do not show private branches, which are included in the list of displayed
branches by default.
.It Fl R , -repo Ar path
Use the
.Xr fossil 1
repository at the specified
.Ar path
for the current
.Nm Cm branch
invocation.
.It Fl r , -reverse
Reverse the order in which branches are displayed.
.It Fl s , -sort Ar order
Sort branches by
.Ar order .
Valid
.Ar order
1207
1208
1209
1210
1211
1212
1213
1214

1215
1216

1217
1218
1219
1220
1221
1222

1223
1224

1225
1226
1227
1228
1229
1230
1231
1232
1233
1234


1235
1236
1237
1238
1239
1240


1241
1242

1243
1244
1245
1246
1247
1248
1249
1235
1236
1237
1238
1239
1240
1241

1242
1243

1244
1245
1246
1247
1248
1249

1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260


1261
1262
1263
1264

1265


1266
1267
1268

1269
1270
1271
1272
1273
1274
1275
1276







-
+

-
+





-
+

-
+








-
-
+
+


-

-
-
+
+

-
+







.It Ic Arrow-up, k
Move selection cursor up one branch.
.It Ic C-f, Page-down
Scroll branch view one page downwards in the buffer.
.It Ic C-b, Page-up
Scroll branch view one page upwards in the buffer.
.It Ic C-d
Scroll branch view half a page downwards in the buffer.
Scroll branch view half of one page downwards in the buffer.
.It Ic C-u
Scroll branch view half a page upwards in the buffer.
Scroll branch view half of one page upwards in the buffer.
.It Ic Home, gg
Move selection cursor to the first branch in the list.
.It Ic End, G
Move selection cursor to the last branch in the list.
.It Ic Enter, Space
Display the
Display a
.Cm timeline
of the currently selected branch.
view of the currently selected branch.
.It Ic c
Toggle coloured output.
On supported terminals,
.Nm
will default to displaying the branch list in colour.
.It Ic d
Toggle display of the date on which the branch last received changes.
.It Ic i
Toggle display of the SHA{1,3} hash that identifies branch, which is the hash
of the commit on the tip of said branch.
Toggle display of the SHA1 or SHA3 hash that identifies each branch,
which is the commit hash of the branch tip.
.It Ic s
Toggle sort order of currently displayed branches.
If branches are ordered lexicographically,
.Nm
will sort branches in most recently used order, otherwise branches will be
sorted by their open/closed state.
will cycle from lexicographical order to most recently used
and then open/closed state.
.It Ic t
Open the
Open a
.Cm tree
view of the currently selected branch.
.It Ic R, C-l
Reload the view with all repository branches, irrespective of which options
were used in this
.Nm Cm branch
invocation.
1261
1262
1263
1264
1265
1266
1267
1268
1269


1270
1271
1272
1273
1274
1275
1276
1277
1278
1279


1280
1281
1282


1283
1284
1285
1286
1287
1288
1289

1290
1291
1292
1293
1294
1295
1296








1297
1298
1299


1300
1301
1302
1303
1304
1305
1306
1307

1308
1309

1310

1311

1312
1313
1314

1315
1316
1317

1318
1319
1320
1321
1322





1323
1324

1325
1326
1327
1328
1329
1330
1331
1332
1333


1334
1335
1336
1337

1338
1339
1340
1341
1342
1343

1344
1345

1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

1367
1368
1369
1370
1371
1372
1373

1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390

1391
1392

1393
1394

1395
1396

1397
1398

1399
1400

1401
1402

1403
1404

1405
1406

1407
1408

1409
1410
1411
1412
1413
1414

1415
1416

1417
1418

1419
1420

1421
1422

1423
1424

1425
1426
1427
1428

1429
1430

1431
1432

1433
1434

1435
1436

1437
1438

1439
1440

1441
1442

1443
1444

1445
1446

1447
1448

1449
1450

1451
1452

1453
1454

1455
1456

1457
1458

1459
1460
1461
1462
1463
1464
1465
1466

1467
1468

1469
1470

1471
1472

1473
1474
1475
1476
1477








1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488


1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1288
1289
1290
1291
1292
1293
1294


1295
1296
1297
1298
1299
1300
1301
1302
1303
1304


1305
1306
1307


1308
1309

1310
1311




1312
1313






1314
1315
1316
1317
1318
1319
1320
1321

1322

1323
1324
1325


1326
1327
1328
1329

1330


1331
1332
1333

1334
1335
1336

1337



1338
1339
1340
1341
1342

1343
1344
1345
1346
1347
1348

1349
1350
1351
1352
1353
1354
1355
1356


1357
1358
1359
1360
1361

1362
1363
1364
1365
1366
1367

1368


1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389

1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

1414


1415
1416

1417


1418
1419

1420


1421
1422

1423


1424
1425

1426


1427
1428
1429
1430
1431
1432

1433


1434
1435

1436


1437
1438

1439


1440
1441
1442
1443

1444


1445
1446

1447


1448
1449

1450


1451
1452

1453


1454
1455

1456


1457
1458

1459


1460
1461

1462


1463
1464

1465


1466
1467
1468
1469
1470
1471
1472
1473

1474


1475
1476

1477


1478
1479
1480



1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494

1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513







-
-
+
+








-
-
+
+

-
-
+
+
-


-
-
-
-
+

-
-
-
-
-
-
+
+
+
+
+
+
+
+
-

-
+
+

-
-




-
+
-
-
+

+
-
+


-
+
-
-
-
+




-
+
+
+
+
+

-
+







-
-
+
+



-
+





-
+
-
-
+




















-
+






-
+
















-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+





-
+
-
-
+

-
+
-
-
+

-
+
-
-
+



-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+

-
+
-
-
+







-
+
-
-
+

-
+
-
-
+


-
-
-
+
+
+
+
+
+
+
+






-
+



-
+
+













.Sh ENVIRONMENT
Depending on the available screen estate determined by the LINES and COLUMNS
environment variables,
.Nm
will display child views in either a horizontal or vertical split.
By default, if COLUMNS is \(>= 120, a child view will open in a vertical split
at least 80 columns wide.
Otherwise, the child view will open in a horizontal split that is approximately
60% of the terminal height.
Otherwise, the child view will open in a horizontal split approximately 60%
of the terminal height.
This behaviour can be customised by configuring the following options as either
exported environment variables or with
.Nm Cm config
as documented above.
.Bl -tag -width FNC_VIEW_SPLIT_HEIGHT
.It Ev FNC_VIEW_SPLIT_MODE
Open child views in a horizontal or vertical split.
Value can be one of
.Sy auto ,
.Sy horizontal ,
.Qq auto ,
.Qq horizontal ,
or
.Sy vertical .
Default:
.Qq vertical
.Pq default: auto .
.Qq auto .
.It Ev FNC_VIEW_SPLIT_HEIGHT
Height of the child view when opening in a horizontal split.
Valid numeric values are 1 \(<=
.Sy n
< LINES.
Percentage values denoted with a postfixed
Integers and percentage values denoted with a postfixed
.Sq %
.Po
e.g.,
.Sy 55%
.Pc
are also valid.
Default:
.Pq e.g., Qq 75%
are valid.
Values that resolve to
.Sy n
lines such that 2 \(<=
.Sy n
< LINES - 2 are accepted while values outside this range are rejected
.Pq default: 60% .
.Qq 60% .
.It Ev FNC_VIEW_SPLIT_WIDTH
Minimum width of the child view when opening in a vertical split.
Minimum width of the child view when opening in a vertical split
.Pq default: 80 .
Currently a no-op.
Default:
.Qq 80 .
.El
.Pp
Similarly,
.Cm diff
options can be persistently applied to all diff views
options can be persistently applied to all diff views whether directly
.Po
i.e., whether directly accessed with
accessed with
.Nm Cm diff
or as a child view
or via the
of the
.Cm timeline
or
.Cm branch
.Cm blame
commands' corresponding key maps
.Pc
by configuring the following options:
views by configuring the following options:
.Bl -tag -width FNC_DIFF_CONTEXT
.It Ev FNC_DIFF_FLAGS
String containing any or all of the available short form
.Cm diff
boolean flag options documented above
boolean flag options documented above except for the
.Fl h
and
.Fl o
options
.Po
i.e., bCilPqsWw
i.e., bCDilPqsWw
.Pc .
If mutually exclusive options
.Qq l
and
.Qq s
are both specified, whichever is last will take precedence; for example,
.Qq lqs
will display side-by-side formatted diffs.
Default: NULL.
will display side-by-side formatted diffs
.Pq default: Qq .
.It Ev FNC_DIFF_CONTEXT
Numeric value as per
the above documented
.Fl x|--context
.Fl x
option
.Po
i.e.,
0 \*(Le n \*(Le 64
.Pc
specifying the number of context lines.
specifying the number of context lines
Illegal values are a no-op.
Default: 5.
.Pq default: 5 .
.El
.Pp
Any options passed to
.Nm Cm diff
will override the above settings.
.Pp
.Nm
displays coloured output by default in supported terminals.
Each colour object identified below can be defined by either exporting
environment variables
.Po e.g.,
.Cm export Ev FNC_COLOUR_COMMIT=red
.Pc ,
or with
.Nm Cm config
as documented above.
At startup,
.Nm
will search for user-defined colours in the following order:
.Bl -column " environment variables " description -offset Ds
.It 1. repository settings Ta Pa repo.fossil
.It 1. repository options Ta Pa repo.fossil
.It 2. environment variables Ta Sy shell
.El
.Pp
If none are found, the default colour scheme will be displayed.
This enables setting per-project colours to visually distinguish the current
repository being viewed, and globally changing the colour scheme for all
repositories with no local settings configured.
repositories with no local options configured.
Except where documented below, colours supported in
.Nm
are:
.Bl -column "black" "yellow" "magenta" "default" -offset indent-two
.It Qo black Qc Ta Qo green Qc Ta Qo blue Qc Ta Qo cyan Qc
.It Qo red Qc Ta Qo yellow Qc Ta Qo magenta Qc Ta Qo default Qc
.El
.Pp
Where
.Qq default
is the current foreground (i.e., text) colour in the terminal.
User-definable colour objects displayed in various
.Nm
views are as follows:
.Bl -tag -width FNC_COLOUR_BRANCH_PRIVATE
.It Ev FNC_COLOUR_COMMIT
The commit hash ID field displayed in the timeline, diff, tree, and blame views.
The commit hash ID field displayed in the timeline, diff, tree, and blame views
If not defined, the default value is
.Qq green .
.Pq default: Qq green .
.It Ev FNC_COLOUR_USER
The username field displayed in the timeline and diff views.
The username field displayed in the timeline and diff views
If not defined, the default value is
.Qq cyan .
.Pq default: Qq cyan .
.It Ev FNC_COLOUR_DATE
The date field displayed in the timeline and diff views.
The date field displayed in the timeline and diff views
If not defined, the default value is
.Qq yellow .
.Pq default: Qq yellow .
.It Ev FNC_COLOUR_DIFF_MINUS
Removed lines displayed in the diff view.
Removed lines displayed in the diff view
If not defined, the default value is
.Qq magenta .
.Pq default: Qq magenta .
.It Ev FNC_COLOUR_DIFF_PLUS
Added lines displayed in the diff view.
Added lines displayed in the diff view
If not defined, the default value is
.Qq cyan .
.Pq default: Qq cyan .
.It Ev FNC_COLOUR_DIFF_HUNK
Hunk header lines
.Po e.g.,
.Li @@ -732,34 +747,40 @@
.Pc
displayed in the diff view.
displayed in the diff view
If not defined, the default value is
.Qq yellow .
.Pq default: Qq yellow .
.It Ev FNC_COLOUR_DIFF_META
Metadata displayed in the diff view.
Metadata displayed in the diff view
If not defined, the default value is
.Qq green .
.Pq default: Qq green .
.It Ev FNC_COLOUR_DIFF_TAGS
The tag field displayed in the diff view.
The tag field displayed in the diff view
If not defined, the default value is
.Qq magenta .
.Pq default: Qq magenta .
.It Ev FNC_COLOUR_DIFF_SBS_EDIT
Changed
.Pq i.e., not added or removed
lines in the diff view when displaying side-by-side diffs.
lines in the diff view when displaying side-by-side diffs
If not defined, the default value is
.Qq red .
.Pq default: Qq red .
.It Ev FNC_COLOUR_TREE_DIR
Directory entries displayed in the tree view.
Directory entries displayed in the tree view
If not defined, the default value is
.Qq cyan .
.Pq default: Qq cyan .
.It Ev FNC_COLOUR_TREE_EXEC
Executable file entries displayed in the tree view.
Executable file entries displayed in the tree view
If not defined, the default value is
.Qq green .
.Pq default: Qq green .
.It Ev FNC_COLOUR_TREE_LINK
Symbolic link entries displayed in the tree view.
Symbolic link entries displayed in the tree view
If not defined, the default value is
.Qq magenta .
.Pq default: Qq magenta .
.It Ev FNC_COLOUR_BRANCH_OPEN
Open branches displayed in the branch view.
Open branches displayed in the branch view
If not defined, the default value is
.Qq cyan .
.Pq default: Qq cyan .
.It Ev FNC_COLOUR_BRANCH_CLOSED
Closed branches displayed in the branch view.
Closed branches displayed in the branch view
If not defined, the default value is
.Qq magenta .
.Pq default: Qq magenta .
.It Ev FNC_COLOUR_BRANCH_CURRENT
The branch corresponding to the current checkout displayed in the branch view.
The branch corresponding to the current checkout displayed in the branch view
If not defined, the default value is
.Qq green .
.Pq default: Qq green .
.It Ev FNC_COLOUR_BRANCH_PRIVATE
Private branches displayed in the branch view.
Private branches displayed in the branch view
If not defined, the default value is
.Qq yellow .
.Pq default: Qq yellow .
.It Ev FNC_COLOUR_HL_LINE
Selected line highlight in the diff view.
Value can be one of
.Sy auto
or
.Sy mono .
The former will invert the foreground colour of the selected line, while the
latter will use a monochromatic highlight.
latter will use a monochromatic highlight
If not defined, the default value is
.Qq auto .
.Pq default: Qq auto .
.It Ev FNC_COLOUR_HL_SEARCH
Search term highlight in blame and diff view.
Search term highlight in the blame and diff views
If not defined, the default value is
.Qq yellow .
.Pq default: Qq yellow .
.El
.Pp
To clear environment variables, issue
.Cm unset Ar ENVIRONMENT_VARIABLE
in the shell.
To clear environment variables, invoke the shell builtin
.Cm unset ;
for example,
.Qq unset Ev FNC_DIFF_CONTEXT .
As documented above, local options can be unset with
.Nm
.Cm config
.Fl u Ar option .
.Pp
.Nm
displays best with UTF-8, and will detect whether UTF-8 is enabled to determine
which characters to draw in certain views.
If UTF-8 is supported by your terminal but is currently disabled, it can be
enabled with
.Qq export LC_ALL=en_US.UTF-8 ;
.Qq export LC_CTYPE=en_US.UTF-8 ;
If not available,
.Nm
will revert to ASCII.
Relatedly, some fonts may render certain characters poorly in the help screen;
Relatedly, some fonts may render certain characters poorly in the help screen
as they lack the requisite glyphs;
.Li Monospace Regular ,
.Li JetBrains Mono ,
and
.Li Menlo
are known to render all characters well.
.Sh EXIT STATUS
.Ex -std fnc
.Sh SEE ALSO
.Xr fossil 1 ,
.Xr sqlite3 1 ,
.Xr re_format 7
.Sh AUTHORS
.An Mark Jamsek Aq Mt mark@jamsek.com

Changes to src/fnc.c.

more than 10,000 changes