Commit fce279e
Compute a document when it is read, and rebuild acr_dm as a set merge (#124)
* Rebuild acr_dm as a set merge, and give package dependencies a type
An ssimfile is a set of rows, and merging one as text throws that away. acr_dm
now merges it as a set: a row is found by its key, and each of its attributes,
the lines above it, and the row it comes after are merged one at a time. One
value stands; two values with the base among them are a change; two values with
the base in neither is a conflict written between markers.
Position is the part a text merge cannot supply. Row order in
data/dmmeta/field.ssim is the member order of a generated struct, so a row that
comes back where the base had it, from a file that moved it, is a struct laid
out the way nobody asked for. Position travels as a tree, each row hanging off
the row it follows, and the merged file is a walk of that tree. Rows that run
consecutively hang off one anchor rather than off each other, which keeps the
walk's depth at the nesting of runs instead of at the number of rows -- a file
one side adds whole used to build a chain as long as itself and overflow the
stack around fifty thousand rows.
A package dependency now says how the two packages stand to each other.
`dev.pkgdeptype` has three values: a **contain** parent distributes the package,
so the parent's content covers it; an **extend** parent does not, so the
parent's content is reduced by whatever the package captures; **require** is
ordering alone. A tree that builds on this one therefore keeps itself out of
the distribution by declaring the relation once, rather than by listing its own
namespaces as negative keys in this package's definition. Two rules decide the
edges: a record a package names outright stays with it, because an extender's
reference closure reaches records it never meant to claim, and the subtraction
runs after every package is evaluated, because packages are evaluated parents
first. `apm -check` reports a namespace two packages claim as
`apm.doubleclaim`.
amc names a generated record from its ctype now. `Instname` is what a ctype
contributes to an identifier, `Varname` is the variable that holds one of its
records, and `Refname` is what a body calls the container; the three had drifted
into each other's jobs, and the instname itself came from whichever field
instantiated the ctype first. Ten ctypes have more than one instance, so for
those, moving two unrelated rows in field.ssim renamed generated identifiers.
A field row's position decides struct layout, and nothing else.
atf_unit finds its own binary again. Taking argv[0] as the path to re-execute
holds only when the tool was started by a path: found on PATH, argv[0] is a bare
word that exec cannot resolve, and given as bin/atf_unit it names a symlink into
a build tree rather than the binary the link points at. Every unit test on a
Linux checkout failed with `can't exec: errno:2`. algo::GetExePath answers with
the file that is really running -- /proc/self/exe where there is one,
_NSGetExecutablePath on Darwin, argv[0] as the last resort -- and both call sites
ask it.
A namespace's internals doc under txt/gen is wholly derived now. abt_md fills a
section a file already carries and never adds one, and the generators for the
table of contents and the description were scoped to README files, so under
txt/gen both sections were carried text that nothing here could reproduce. Both
generators match a txt/gen mdfile as well, and a description there is one line
pointing at the namespace's usage README, titled from its dmmeta.ns comment. A
README elsewhere keeps the description someone wrote for it. The Functions
section a library's doc carries comes back the same way, from src_func over that
namespace's own sources.
The rule files for acr, acr_dm, acr_ed, amc and openacr arrive with their
dev.readmefile rows, so abt_md maintains their headings and links here rather
than leaving them as files it does not know about.
txt/lib/lib_ams/README.md lists the process types this tree's own amsdb defines.
It had been carrying the table from the tree that publishes this one, which names
processes no target here builds.
Two scripts under test/lstw are gone. Nothing here reads them and no target
here ever did; they came across in an earlier publication and stayed, because a
publication adds and rewrites files without removing one that has left the
distribution.
CI builds and tests on macOS as well as Linux. The runner is `macos-26`, a
standard Apple Silicon machine and therefore free for a public repository, and
arm64 is the arch this tree can describe: `dev.tool_opt` carries
`Darwin-%.%-arm64` rows and nothing for Darwin x86_64. The image has to be
macOS 26 rather than 15, because the Darwin arm64 build passes
`-Wno-cast-function-type-mismatch` and `-Wno-nontrivial-memcall`, which clang
learned in 19 and 20; `macos-15` defaults to Xcode 16.4, whose clang is 17, and
under `-Werror` an older clang rejects the unknown option itself and fails the
bootstrap's first compile. `fail-fast: false` keeps
the Linux leg reporting when macOS fails, the macOS leg is `continue-on-error`
until it goes green, and `memcheck` is a Linux-only step because valgrind has no
macOS arm64 port.
Two things that leg needs in order to link. Homebrew keeps openssl and the
mariadb connector keg-only, so neither reaches `/opt/homebrew/include`, while
`include/sha.h` includes `<openssl/evp.h>` unconditionally and five Darwin
targets link `crypto` or `ssl`; four `dev.tool_opt` rows name those two kegs in
the shape the readline rows already used. And `lib_mysql` compiles
`<mariadb/mysql.h>` while its Darwin row asked the linker for `mysqlclient`,
which belongs to a different package -- the row says `mariadb` now, the library
Linux already links.
Where macOS code goes is written down. A call Linux provides and macOS does not
belongs in `cpp/lib/algo/macos.cpp`, inside one `#if defined(__MACH__)` spanning
the file, because `dev.targsrc` names a target and a source with no uname between
them: every source in a target compiles on every platform, so nothing short of a
file-wide condition can make a source macOS-only. A conditional choosing between
two bodies of one function is not that, and neither is one in a header.
That file exists now, and two Linux-only calls put it there -- different in kind,
which is what the rule is for. `algo::GetNcore` reads the affinity mask under
`#ifndef WIN32`, and `cpu_set_t` exists on Linux alone, so the guard says
`__linux__` and every other system takes the online count that was already the
fallback; nothing moves, because nothing was missing. `pipe2` is genuinely
absent on Darwin, so `cpp/lib/algo/macos.cpp` supplies it: both ends get their
flags immediately after the pipe, and a flag it cannot apply is refused rather
than quietly dropped, since dropping the O_CLOEXEC a caller asked for reopens the
fork window the call exists to close.
The line-ending citest converts with perl rather than `sed -i`. BSD sed wants a
suffix after `-i`, so it took the script as one and then read the filename as the
script -- `txt/README.md` parsed as sed's `t` command, reporting an undefined
label named after the file. Every invocation failed, the citest modified nothing,
and it therefore reported success: on macOS it was inert rather than red, which is
the worse of the two. `perl -pi -e` takes no suffix on either system, and the
filename is quoted now instead of spliced raw.
A tutorial's recorded output no longer names the machine that produced it.
`abt.config` reports the builddir it built in, and a doc generated on Linux
therefore said `Linux-g++.release-x86_64` where a macOS run says
`Darwin-clang++.release-arm64`; the value is a property of whoever ran the
command, exactly like the `ood_src` and `cache` beside it, so it joins them in
`dev.unstablefld` and renders as `***`.
The Darwin link line asks its linker not to warn about duplicate archives.
Repeating an archive is deliberate here -- a library is emitted before and after
its own dependencies so that a single-pass linker can close a cycle, and there
is a second `algo_lib` after `gen_lib` for the same reason. A multi-pass linker
has no need of the repetition and says so, once per link, which lands in the
recorded output of every doc that builds something.
Two amc tests say what they mean on a system that serves a big block without
mapping it. `SbrkMmapTrace` asserts that a request no mapping can serve counts
no mapping, and it wrote that as `n_mmap == nmmap + 1` -- the plus one being what
the *successful* request before it happened to count where big blocks are mapped.
It takes that reading now instead of assuming it, so the assertion holds its
force either way rather than being switched off by platform. And
`TaryInsaryBadIndex` reports what the child process did, since a fatal exit, a
crash while composing the fatal report, and a bounds check that never fired are
three different repairs behind one failed assertion.
A fail-stop emits its enrichment one piece at a time. The cause already went out
before anything that could fail to state it, on the principle that a report must
not depend on the resource whose absence it reports; the build stamp, the
backtrace and the trace counters were then composed together and emitted at the
end, so a crash while composing any of them discarded all three. Each goes out
as it is composed now, which costs a dying process two extra writes and means the
record ends at the stage that died. The test that provokes a fail-stop names a
record file too, since its child discards stderr and the record is otherwise the
only account of how far the path ran.
The counters go out one database at a time for the same reason, and each database
is named before its table is touched. Reading a database's counters means
calling through the function pointers its generated reflection installed, so a
table that cannot be printed kills the process there, and the record now ends
with the name of that database instead of losing every database that printed
cleanly before it.
That record named the defect, and it is not a Darwin one. A ctype's `_Print` is
generated to take its row by value when the ctype is plain data of at most sixteen
bytes, while reflection calls a printer through `algo::ImrowPrintFcn`, which takes
an `ImrowPtr` -- and the registration bridged the two with a cast. A by-value
printer therefore received the row across as many argument slots as it has
eightbytes and read its `cstring` from the wrong register. Where the row goes by
reference the two agree, a reference being a pointer on every target, so this
survived until a table small enough to be register-passed met an ABI that passes
small structs in registers: `lib_json.trace` has two counters, exactly the
boundary. A by-value printer now gets a generated `_PrintImrow` carrying the
signature reflection calls, and the registration has no cast in it.
`txt/exe/apm/internals.md` is gone. It describes the publishing tree's own
internals, no key here names it, and its links into `txt/exe/amc/reftype.md`
pointed at anchors that moved when the ssimdb documents became one file per
reftype -- so `abt_md` reported fourteen dangling anchors in a file nothing here
owns.
Three unit tests were reading Linux for a rule. `algo_lib.FProc` asks whether a
pipe the parent holds reaches a child spawned afterwards, and it answered by
matching the pipe's `/proc/self/fd` name in a listing the child made of its own
descriptors -- a directory macOS does not have, so the helper found no name and
reported no leak whichever way the flag was set. It asks the child to read from
the descriptor instead, which tests the consequence rather than the bookkeeping
and needs no way to enumerate another process's descriptors.
`algo_lib.Mmap` asserts that a write through another handle shows up in the
mapping, and `MmapFile_LoadFd` mapped MAP_PRIVATE, which leaves that unsaid: the
standard does not decide whether a later write reaches a private mapping, Linux
lets it through and Darwin does not. The mapping is MAP_SHARED now. Nothing is
written through it, it being PROT_READ, so sharing costs nothing and the two
systems answer alike.
`algo_lib.Decimal` compared two conversions of one number that were never the
same function. `Decimal_GetDouble` computed the mantissa times `pow(10,
exponent)` while the parser builds its scale by repeated multiplication, and no
power of ten above 10^22 is representable in a double, so the two land on
different ones -- 2.7e-16 apart at 10^-63 under glibc, which is 27% of the
tolerance the test allows, and further apart under a libm whose `pow` is less
accurate for a large integral exponent. What a decimal is worth as a double is
what this tree's own parser makes of it, so `Decimal_GetDouble` prints and
parses, and there is one definition of that rather than two.
`fstep_TimeHookRecur` counted the platform's sleep and called it the mechanism.
`bh_timehook_Step` reschedules a recurrent hook from the loop's own clock rather
than from the deadline it just met, so the period is a floor: a cycle that
returns late pushes the next firing out by however late it was, and what the
count measures is whatever `nanosleep` managed. A tenth of a second at a
hundredth-second period fires ten times on Linux and three times on a macOS
runner, and neither is the hook misbehaving. The window is a second now, long
enough that a coarse sleep still leaves plenty of firings, and the bounds state
what is actually promised -- that the hook keeps firing, and that it never
outruns its period, which is a hundred firings in the window plus the immediate
one. The test reports the count it saw rather than only that the count was
wrong.
`acr_dm.DeepRun` counted lines with `wc`, which pads its count to a column width
on a BSD userland and not on a GNU one, so one run printed `100000` and the other
` 100000`. `awk "END{print NR}"` prints the number and nothing beside it on
either.
gcache told the compiler its input was already preprocessed by passing
`-fpreprocessed`, which is gcc's own spelling and which clang refuses outright.
The command line already carries an `-x`, put there by `dev.tool_opt`, and gcache
already rewrites it -- a precompile turns `c++` into `c++-header` -- so the
preprocessed case joins it as `c++-cpp-output`, which both drivers read. It has
to be that `-x` and not an appended one, because `-x` applies to the inputs after
it and one placed past the source applies to nothing. The precompiled-header
build keeps `-fpreprocessed`: its input is a header rather than a `.ii`, and that
path emits `#pragma GCC pch_preprocess`, so it is gcc's either way.
The gcache comptests reached for a GNU userland in two more places. `stat -c%s`
names the flag GNU's stat takes and BSD's does not, so the size it was meant to
feed `truncate` arrived empty and truncate refused a size of `-`. `$(( $(wc -c <
f) ))` reads the size on either, and the arithmetic strips the column padding a
BSD wc adds. `touch -d 2020-01-01` is GNU's spelling of a timestamp, and `touch
-t 202001010000` is the spelling both accept.
The header gcache writes for that build is named `.hpp` rather than `.h`, since a
driver reads the language off the suffix and `.h` is a C header to both of them.
g++ takes it as C++ anyway and says nothing, while clang++ obeys the suffix and
warns on every compile that it is treating a C header as C++. gcache already
writes C++ everywhere else -- the preprocessed file it makes is a `.ii` -- so the
suffix now says what the file is.
A precompiled header that fails to build no longer fails the compile. gcache
counted that failure into its exit code and then skipped the compile, so a driver
that does not read gcc's own `pch_preprocess` pragma stops every build that goes
through the cache. The header is an optimization; the compile proceeds without
it, and gcache says on stderr that it did.
A failed leg repeats its own tail as an annotation. Downloading a job's log
needs admin rights on the repository, so a contributor reading a red check sees
that something failed and nothing about what -- and the macOS leg is the one that
fails, on a machine most people here do not have. An annotation needs no rights,
rides on the check run, and is what the workflow now emits from the last six
kilobytes of the run: the citest that died, and what it printed.
Alongside that: fbuf and avl reworked, atf_comp restructured around a process
wrapper, and atf_unit and atf_ci taken from the tree that publishes this one.
* Compute a document when it is read, and add the tool that does it
`doc` renders any document of this tree, any source file, and any record of the
ssim database -- at the terminal, as an HTML page, or from an HTTP server it runs
itself. The argument is a key: any substring of a `dev.readmefile` path, the name
of a documented thing, or, when it carries a colon, an acr query. So a page that
used to be committed as markdown is synthesized when it is asked for, and
`txt/gen`, the per-ctype documents under `txt/protocol` and the per-table
documents under `txt/ssimdb` are gone -- 333 files, answered on demand out of data
that cannot go stale.
At the terminal the arrows move a selection between the page's links, Enter opens
one and Backspace returns. `e` runs the editor on the document, or on the query
with `-e` added to it. `m` asks acr for the schema of the selection, which is
records too and is walked with the same keys. `-html` writes the same page for a
browser and `-bind` serves it, and the navigation pane is one markdown text, drawn
above the page at the terminal and beside it in a browser.
The command line a page shows is one `doc` accepts, so a reader can type back what
they see, and a display state that is not an option of `doc` may not appear there.
`dev.docpage` is the vocabulary: a row per synthesized page, bound to
`doc::docpage_<name>`, and both devices dispatch through it.
`msg` is the protocols, which is to say every message header in the tree.
`msg:ams.MsgHeader` is that header and the messages that begin with it, each with
its type and its size. `msg:ams.LogMsg` is that message, its wire layout field by
field, and the dispatches that receive it, which lead on to the handler's source.
Nothing wrote that relation down; it is `dmmeta.typefld` and the Base fields,
walked.
`abt_md` generates a title, a syntax block, an options list, an inputs list and a
handful of protocol tables, and nothing else, so `dev.mdsection` is eight rows
where it was twenty-six. It takes the namespace of a help declaration as the text
before the first underscore outside the string: a tool's help opens by naming the
tool, and `atf_unit_help = "atf_unit: ...` had its last underscore inside the
string, which left a third of the tool READMEs carrying no Syntax section. A
document's title is recorded on its `dev.readmefile` row, so a listing need not
open the file to name it. `acr_ed` no longer writes a markdown file per ssim
table.
`amc` keeps the `dmmeta.msg` and `dmmeta.msgfield` rows of a message that ends in
a varlen tail. The walk refused a field it could not place, which is right for a
field with something after it and wrong for the last one, and twenty-two messages
under `ams.MsgHeader` were being dropped entirely. The access list above a struct
leaves Base out, since that list is confined to one namespace and a Base relation
rarely is -- a header named the few messages beside it and none of the hundred
elsewhere.
Every rule file under `txt/rule` is titled `<ns>: Rules`. A title naming what the
file happens to say today goes stale as soon as it grows a section about something
else, and leaves a reader scanning the directory unable to tell which namespace it
belongs to.
Every `txt/ssimdb` README stays, including the nineteen holding only a computed
title. Some 2,900 committed links name a table as
`txt/ssimdb/<ns>/README.md#<ns>-<name>`, and a link whose path is not a file git
tracks is rejected. 683 fenced blocks under `txt/` gained a language, a bare
fence having reached the shell lexer and coloured ssim and C++ as shell.
The page footer claims no copyright. This tree is GPL, and the license travels
with the source and says what a reader may do with it, so the footer carries the
moment of the commit the running binary was built from and that commit's ref, and
names nobody.
* Resolve what the sync left behind, and guard a single match by its own pointer
Four checks were red, and each names a different way a document or a table can
outlive the thing it described.
`dev.readmesort` is gone, so `data/dev/readmesort.ssim` goes with it. The table
ordered a chapter listing that is no longer generated; its catalog row left with
the sync and the file stayed, since nothing manages `data/` for it.
`update-gitfile` drops the row naming it.
`txt/lib/lib_prot/README.md` no longer offers an `Internals` link. It pointed
into `txt/gen`, which is not a directory this tree has, and the section is carried
text that no `dev.mdsection` row regenerates or removes.
Two rule files illustrate themselves with tables this tree has. `abt_md` resolves
a `ssimfile:` span against the database it runs in, so an example naming a table
absent here is a dangling reference rather than a link: the field rename in
`txt/rule/acr_ed.md` renames `dev.Htmlentity.code`, and the short-name span in
`txt/rule/openacr.md` names `dmmeta.ctype`.
`ShortkeyQ` dereferences `only` under a null test rather than under a count. The
pointer and the counter said the same thing, and only the pointer says it to a
static analyzer -- `only` now holds the candidate while there is exactly one, and
a second match clears it.
---------
Co-authored-by: Alexei Lebedev <alexei@algox2.com>1 parent 2c23284 commit fce279e
969 files changed
Lines changed: 62836 additions & 80918 deletions
File tree
- .github/workflows
- bin
- bootstrap
- conf
- cpp
- abt_md
- abt
- acr_dm
- acr_ed
- acr
- amc
- disp
- apm
- atf_amc
- atf_ci
- atf_comp
- atf_unit
- doc
- gcache
- gen
- lib_sqlite
- lib_ws
- lib
- algo
- data
- amcdb
- amsdb
- atfdb
- dev
- dmmeta
- include
- gen
- test
- abt_md
- acr_dm
- atf_comp
- ts/gen
- txt
- exe
- abt_md
- abt
- acr_compl
- acr_dm
- acr_ed
- acr_in
- acr_my
- acr
- amc_gc
- amc_vis
- amc
- backend
- reftype
- ams_sendtest
- amsspy
- apm
- aqlite
- atf_amc
- atf_ci
- atf_cmdline
- atf_comp
- atf_cov
- atf_fuzz
- atf_nrun
- atf_unit
- bash2html
- doc
- gcache
- jkv
- mdbg
- mysql2ssim
- orgfile
- samp_make
- samp_meng
- samp_regx
- src_func
- src_hdr
- src_lim
- ssim2csv
- ssim2mysql
- ssimfilt
- strconv
- sv2ssim
- wt
- gen
- abt_md
- abt
- acr_compl
- acr_dm
- acr_ed
- acr_in
- acr_my
- acr
- algo_lib
- amc_gc
- amc_vis
- amc
- ams_sendtest
- amsspy
- apm
- aqlite
- atf_amc
- atf_ci
- atf_cmdline
- atf_comp
- atf_cov
- atf_fuzz
- atf_nrun
- atf_unit
- bash2html
- gcache
- jkv
- lib_amcdb
- lib_ams
- lib_ctype
- lib_curl
- lib_exec
- lib_git
- lib_http
- lib_iconv
- lib_json
- lib_mysql
- lib_netio
- lib_prot
- lib_rl
- lib_sqlite
- lib_sql
- lib_ws
- mdbg
- mysql2ssim
- orgfile
- samp_make
- samp_meng
- samp_regx
- src_func
- src_hdr
- src_lim
- ssim2csv
- ssim2mysql
- ssimfilt
- strconv
- sv2ssim
- wt
- lib
- algo_lib
- lib_amcdb
- lib_ams
- lib_ctype
- lib_curl
- lib_exec
- lib_git
- lib_http
- lib_iconv
- lib_json
- lib_mysql
- lib_netio
- lib_prot
- lib_rl
- lib_sqlite
- lib_sql
- lib_ws
- openacr
- protocol
- algo
- ams
- atf
- command
- fm
- http
- ietf
- js
- kafka
- report
- ws
- rule
- script
- ssimdb
- amcdb
- amsdb
- atfdb
- dev
- dmmeta
- httpdb
- sampdb
- wsdb
- tut
- www/doc
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
15 | 21 | | |
16 | 22 | | |
17 | 23 | | |
18 | 24 | | |
19 | 25 | | |
| 26 | + | |
20 | 27 | | |
21 | 28 | | |
22 | 29 | | |
| |||
28 | 35 | | |
29 | 36 | | |
30 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
31 | 47 | | |
32 | 48 | | |
33 | 49 | | |
34 | 50 | | |
35 | 51 | | |
36 | | - | |
37 | | - | |
| 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 | + | |
38 | 88 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
22 | 27 | | |
23 | 28 | | |
24 | 29 | | |
| |||
76 | 81 | | |
77 | 82 | | |
78 | 83 | | |
| 84 | + | |
79 | 85 | | |
80 | 86 | | |
81 | 87 | | |
| |||
91 | 97 | | |
92 | 98 | | |
93 | 99 | | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | 100 | | |
102 | | - | |
| 101 | + | |
103 | 102 | | |
104 | 103 | | |
105 | | - | |
| 104 | + | |
106 | 105 | | |
107 | 106 | | |
108 | 107 | | |
109 | 108 | | |
110 | | - | |
| 109 | + | |
111 | 110 | | |
112 | 111 | | |
113 | 112 | | |
114 | 113 | | |
115 | | - | |
| 114 | + | |
116 | 115 | | |
117 | 116 | | |
118 | 117 | | |
| 118 | + | |
| 119 | + | |
119 | 120 | | |
120 | 121 | | |
121 | 122 | | |
122 | 123 | | |
123 | | - | |
| 124 | + | |
124 | 125 | | |
125 | 126 | | |
126 | 127 | | |
0 commit comments