Skip to content

Commit

Permalink
Add the csreconst, file reconstutition command
Browse files Browse the repository at this point in the history
  • Loading branch information
dspinellis committed Dec 10, 2024
1 parent fe60115 commit 48d6fdf
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 5 deletions.
2 changes: 1 addition & 1 deletion doc/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
DESTDIR=/dds/pubs/web/home/cscout
NOTETOOLS=/dds/pubs/courses/tools
MANDOC=mancscout.xml mancswc.xml mancsmake.xml mancscc.xml mancscut.xml \
mancssplit.xml
mancssplit.xml mancsreconst.xml

.SUFFIXES:.java .dot .ps .gif .pic .eps .png .1

Expand Down
7 changes: 4 additions & 3 deletions doc/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@
<ch><ti>Error Messages</ti><fi>error</fi></ch>
<ch><ti>License</ti><fi>license</fi></ch>
<ch><ti>Frequently Asked Questions</ti><fi>faq</fi></ch>
<ch><ti>The cscout Command Manual Page</ti><fi>mancscout</fi></ch>
<ch><ti>The cswc Command Manual Page</ti><fi>mancswc</fi></ch>
<ch><ti>The csmake Command Manual Page</ti><fi>mancsmake</fi></ch>
<ch><ti>The cscc Command Manual Page</ti><fi>mancscc</fi></ch>
<ch><ti>The cscout Command Manual Page</ti><fi>mancscout</fi></ch>
<ch><ti>The cscut Command Manual Page</ti><fi>mancscut</fi></ch>
<ch><ti>The csmake Command Manual Page</ti><fi>mancsmake</fi></ch>
<ch><ti>The csreconst Command Manual Page</ti><fi>mancsreconst</fi></ch>
<ch><ti>The cssplit Command Manual Page</ti><fi>mancssplit</fi></ch>
<ch><ti>The cswc Command Manual Page</ti><fi>mancswc</fi></ch>
<ch><ti>Bibliography</ti><fi>bib</fi></ch>
<ch><ti>Change History</ti><fi>change</fi></ch>
</index>
2 changes: 1 addition & 1 deletion man/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
all: cscout.pdf cswc.pdf csmake.pdf cscc.pdf cscut.pdf cssplit.pdf
all: cscout.pdf cswc.pdf csmake.pdf cscc.pdf cscut.pdf cssplit.pdf csreconst.pdf

%.pdf: %.1
groff -Tps -man <$< >$$.ps
Expand Down
103 changes: 103 additions & 0 deletions man/csreconst.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
.TH CSRECONST 1 "10 December 2024"
.\"
.\" (C) Copyright 2024 Diomidis Spinellis
.\"
.\" This file is part of CScout.
.\"
.\" CScout is free software: you can redistribute it and/or modify
.\" it under the terms of the GNU General Public License as published by
.\" the Free Software Foundation, either version 3 of the License, or
.\" (at your option) any later version.
.\"
.\" CScout is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with CScout. If not, see <http://www.gnu.org/licenses/>.
.\"
.SH NAME
csreconst \- Test the reconstitution of files from a CScout database
.SH SYNOPSIS
\fBcsreconst\fP -t [\fB-ckqs\fP] \fIdatabase.db\fP
.br
\fBcsreconst\fP -f \fIfile\fP [\fB-o\fP] [\fB-b\fP \fIline\fP] [\fB-e\fP \fIline\fP] ... \fIdatabase.db\fP
.SH DESCRIPTION
\fIcsreconst\fP is a utility for testing the reconstitution of files
stored in a \fICScout\fP database or reconstituting specific files.
.PP
The program provides two modes of operation:
.TP
\fB-t\fP
Test the reconstitution of all files in the specified SQLite \fIdatabase.db\fP.
Additional options can be specified to refine the behavior of the testing:
.TP
\fB-c\fP
Count the number of correct and incorrect files.
.TP
\fB-k\fP
Keep comparing after finding a difference.
.TP
\fB-q\fP
Run a quick diff without listing the full differences.
.TP
\fB-s\fP
Provide a summary of each file's reconstitution result.
.PP
\fB-f\fP
Reconstitute a specified \fIfile\fP stored in SQLite \fIdatabase.db\fP.
Additional options allow fine-grained control of the reconstitution:
.TP
\fB-b \fIline\fP
Reconstitute starting from the specified beginning line number.
.TP
\fB-e \fIline\fP
Reconstitute up to the specified ending line number.
.TP
\fB-o\fP
Prefix each reconstituted part with its file offset value.
.SH EXAMPLES
Test all files in a \fICScout\fP database and provide a summary:
.PP
.DS
.ft C
.nf
csreconst -tckqs result.db
.ft P
.fi
.DE
.PP
Reconstitute the file \fCmain.c\fP from a \fICScout\fP database:
.PP
.DS
.ft C
.nf
csreconst -f main.c result.db
.ft P
.fi
.DE
.PP
Reconstitute file \fCmain.c\fP from line 10 to line 50,
listing the offset of each part:
.PP
.DS
.ft C
.nf
csreconst -f main.c -b 10 -e 50 -o result.db
.ft P
.fi
.DE
.SH EXIT STATUS
The exit code indicates the result of the comparison operation:
.TP
0
All files compare equal (no differences found).
.TP
1
Differences were found between the reconstituted and original files.
.SH "SEE ALSO"
cscout(1),
csmake(1)
.SH AUTHOR
(C) Copyright 2024 Diomidis Spinellis.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ uninstall:
rm -f "$(PREFIX)/bin/cswc"
rm -f "$(PREFIX)/bin/cscut"
rm -f "$(PREFIX)/bin/cssplit"
rm -f "$(PREFIX)/bin/csreconst"
rm -rf "$(PREFIX)/include/cscout"
for i in ../man/*.1 ; do rm -f $(MANDIR)/$$(basename $$i) ; done

Expand Down
245 changes: 245 additions & 0 deletions src/csreconst.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
#!/bin/bash
#
# (C) Copyright 2024 Diomidis Spinellis
#
# This file is part of CScout.
#
# CScout is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CScout is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CScout. If not, see <http://www.gnu.org/licenses/>.
#
# Reconstitute source code files from a CScout database.
#

set -eu

# Create a temporary directory and set up a trap for cleanup
temp_dir=$(mktemp -d) || exit 1
# Clean up on exit or signals
trap 'rm -rf "$temp_dir"' EXIT


# Display usage information and exit
usage()
{
local message="$1"

cat <<EOF 1>&2
$message
Usage: $(basename $0) -t [-ckqs] database.db
$(basename $0) -f file [-o] [-b line] [-e line] ... database.db
Test the reconstitution of files in a CScout database
-t Test the reconstitution of all files.
Available options:
-c Count correct and incorrect files
-k Keep comparing after finding a difference.
-q Run a quick diff; do not list the full diff output.
-s Provide summary of each file's result.
-f file Reconstitute the specified file.
Available options:
-b line Beginning line number.
-e line Ending line number.
-o Output offset values.
EXAMPLES
Test all files providing a summary.c:
test-reconst -tckqs result.db
Reconstitute file.c:
test-reconst -f file.c result.db
EOF
exit 1
}

opt_test=''
opt_keep_going=''
opt_quick=''
opt_summary=''
opt_count=''

opt_file=''
opt_begin='0'
opt_end='99999999'
opt_offset=''

# Process command-line arguments
while getopts "tckqsf:b:e:o" opt; do
case $opt in
c)
opt_count=1
;;
b)
opt_begin="(SELECT foffset FROM linepos CROSS JOIN selected_file AS sf
WHERE fid=sf.value AND lnum <= $OPTARG LIMIT 1)"
;;
e)
opt_end="(SELECT foffset FROM linepos CROSS JOIN selected_file AS sf
WHERE fid=sf.value AND lnum >= $OPTARG LIMIT 1)"
;;
f)
opt_file="$OPTARG"
;;
k)
opt_keep_going=1
;;
o)
opt_offset='foffset, '
;;
q)
opt_quick=-q
;;
s)
opt_summary=1
;;
t)
opt_test=1
;;
\?) # Illegal option
usage ''
;;
:)
usage "Option -$OPTARG requires an argument."
;;
esac
done

shift "$((OPTIND-1))"

# Database must be provided
test $# -ne 1 && usage "Database name not specified"
DB="$1"

# Both cannot be set
test -n "$opt_file" -a -n "$opt_test" && usage "-t and -f cannot both be set"

# At least one must be set
test -z "$opt_file" -a -z "$opt_test" && usage "At least one of -t or -f must be set"


# Run diff on the specified path with output controlled by opt_quick
run_diff()
{
local path="$1"

if [ -n "$opt_quick" ] ; then
diff $opt_quick -w $path $temp_dir/reconstructed.c >/dev/null
else
diff $opt_quick -w $path $temp_dir/reconstructed.c
fi
}

# Output the selection query for all elements of the specified file
all_elements()
{
local fid="$1"

cat <<EOF
SELECT foffset, name AS s
FROM ids
INNER JOIN tokens USING(eid)
WHERE fid = $fid
UNION
SELECT foffset, code AS s
FROM rest
WHERE fid = $fid
UNION
SELECT foffset, comment AS s
FROM comments
WHERE fid = $fid
UNION
SELECT foffset, string AS s
FROM strings
WHERE fid = $fid
EOF
}

# Fix newlines
fix_nl()
{
tr -d "\n\r" |
perl -pe 's/\\u0000d\\u0000a/\n/g;s/\\u0000a/\n/g'
}

# Test reconstitution of all files
test_all()
{
local nfiles=0
local same=0
local different=0
local result_file="$temp_dir/results"
local exit_status=0


sqlite3 "$DB" 'select distinct fid, name from files;' |
while IFS='|' read fid path ; do
echo "SELECT s FROM ( $(all_elements $fid) ) ORDER BY foffset;" |
sqlite3 "$DB" |
fix_nl >$temp_dir/reconstructed.c

test -n "$opt_count" && echo files >>$result_file
if run_diff "$path" ; then
test -n "$opt_summary" && echo$path
test -n "$opt_count" && echo same >>$result_file
else
local result=$?
test -n "$opt_summary" && echo$path
test $result -ne 0 -a -z "$opt_keep_going" && exit 1
test -n "$opt_count" && echo different >>$result_file
fi
done

if [ -n "$opt_count" ] ; then
awk 'BEGIN {s = d = 0 }
/same/{s++}
/different/{d++}
END {
print s + d " files " s " same " d " different";
exit d != 0
}' $result_file
exit_status=$?
fi

exit $exit_status
}

# List the contents of a single file
file_list()
{
cat <<EOF |
WITH selected_file AS (
SELECT fid AS value FROM files WHERE name='$opt_file'
),
elements AS (
$(all_elements '(SELECT value from selected_file)')
)
SELECT $opt_offset s
FROM elements
WHERE foffset BETWEEN
$opt_begin
AND
$opt_end
ORDER BY foffset;
EOF
sqlite3 "$DB" |
if [ -n "$opt_offset" ] ; then
cat
else
fix_nl
fi
}

test -n "$opt_test" && test_all
test -n "$opt_file" && file_list "$opt_file"
1 change: 1 addition & 0 deletions src/dest-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,6 @@ install $TMPFILE "$PREFIX/bin/cscc"

install cscut.sh "$PREFIX/bin/cscut"
install cssplit.awk "$PREFIX/bin/cssplit"
install csreconst.sh "$PREFIX/bin/csreconst"

rm -f $TMPFILE

0 comments on commit 48d6fdf

Please sign in to comment.