\input cwebmac
%%% ====================================================================
%%%  @C-Web-file{
%%%     author          = "Robert M. Solovay",
%%%     version         = "1.04",
%%%     date            = "15 March 1993",
%%%     time            = "16:58:07 MST",
%%%     filename        = "checksum.w",
%%%     address         = "Department of Mathematics
%%%                        University of California
%%%                        Berkeley, CA
%%%                        USA
%%%                        Tel: (415) 642-2252",
%%%     checksum        = "43506 1194 6727 43473",
%%%     email           = "solovay@math.berkeley.edu (Internet)",
%%%     codetable       = "ISO/ASCII",
%%%     keywords        = "checksum",
%%%     supported       = "yes",
%%%     docstring       = "The checksum field above contains a CRC-16
%%%                        checksum as the first value, followed by the
%%%                        equivalent of the standard UNIX wc (word
%%%                        count) utility output of lines, words, and
%%%                        characters.  This is produced by checksum
%%%                        itself.",
%%%  }
%%% ====================================================================

%%% Revision history (reverse time order):
%%%
%%% 1.04 [15-Mar-1993]
%%%	Add support for Apple Macintosh.
%%%
%%% 1.03 [25-Jun-1992]
%%%	Add support for VAX VMS C run-time library deficiency.
%%%
%%% 1.02 [11-Sep-1991]
%%%	Add missing initialization of answer_from_critical; this bug
%%%	was discovered when garbage output was produced from an empty
%%%	input file.
%%%
%%%	Correct two ">From" strings to "from" (mangled by UNIX mailer).
%%%
%%%	Shorten two long lines to <= 80 characters.
%%%
%%% 1.01 [06-Sep-1991]
%%%	Minor wording changes.
%%%
%%%	Add EXIT_SUCCESS and EXIT_FAILURE, and use in all exit()
%%%	calls.  Make successful checksum installation or verification
%%%	return EXIT_SUCCESS, and all other conditions, EXIT_FAILURE,
%%%	so shell commands can test execution status.
%%%
%%%	Add missing initialization of verify_successful.
%%%
%%% 1.00 [04-Mar-1991]
%%%	Original version.
%%%
%%% ====================================================================


\N1.  The checksum program.
\medskip
Copyright 1991 Robert Solovay -- University of California, Berkeley.
Email: solovay@math.berkeley.edu
\medskip
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.  This software is provided ``as is'' without express or
implied warranty.



\medskip
This program will compute a 16-bit cyclic redundancy checksum
(CRC)
for a file as well
as a count of the words, lines and characters. If called from the
command line with:

{\tt \%checksum  inputfile outputfile}

{\parindent=0pt the program will compute a 16-bit  checksum for the file
{\sl inputfile} and write a copy of this file with the checksum
installed to the file {\sl outputfile}.}

If the checksum has previously been installed in the input file, and
the input file has not been corrupted since then,
the output file will be identical to the input file.

If called with the command line:

{\tt \%checksum -v file}

{\parindent=0pt where {\sl file} is a file with an ``installed''
checksum, the program will proceed to verify whether the checksum is
correct and report its conclusions to \\{stdout}.}
%Here is the checksum for this web file:
%checksum = "02100 1108 6383 40704"
\fi

\M2. More precisely, the program will search for the first line of
{\sl inputfile}
which contains the word {\sl checksum} in lowercase and no other
alphabetic characters. We refer to this line as the ``critical line''
of the file. If the critical line contains no quotation marks, then
the file {\sl outputfile} will be created
which is a copy of {\sl inputfile} except that the critical line
will be replaced by a line where the word {\tt checksum} is
replaced by {\tt checksum = "xxxxx lc wc cc"}. Here {\sl lc} is the
number of lines in the file {\sl outfile}, written in decimal.
Similarly, {\sl wc}
is the word count of {\sl outfile} and {\sl cc} is the character count
(when the end of line character is taken to be the single character
\.{\\n}.)

It is difficult to arrange that a file contains its own
checksum. Instead,
the field {\sl xxxxx} contains the checksum,  written in
decimal in a five-digit field (with  possible leading 0's) of the file
obtained from {\sl outfile} by replacing the field containing the
checksum by the string \.{"ZZZZZ"}.

If the critical line already contains after the word
``checksum'' precisely two quotation marks, and the first is the last
character of the four-character string \.{"\ =\ \\""}, then the material
between the two quotes will be deleted and replaced by a checksum and
three counts as described above.

The program is designed to be usable as a UNIX filter; that
is, it can take its input from \\{stdin} or send its output to \\{stdout}.
The user can indicate the choce of \\{stdin} or \\{stdout} either by
omitting the relevant file-name from the command line or by using the
single character \.{'-'}. (If the command given is:

{\tt \%checksum file}

{\parindent=0pt the program will interpret \\{file} as the name of the
input file, and will send the output to \\{stdout}.)}

\fi

\N3.  The skeleton.
Here is the main module of the program.

\Y\B\X11:Global type definitions\X\6
\X4:Global \#\&{include}s\X\6
\X5:Global variables\X\6
\X15:All functions\X\6
\X6:Main\X\par
\fi

\M4.
We have to include the standard I/O definitions, as well as some
other standard header files.  Until all C implementations reach
the level of the 1989 ANSI C standard, we have to be careful about
which files we try to include.  The GNU C compiler defines the
symbol \.{\_\_STDC\_\_}, but is commonly run with native pre-ANSI header
files.
\Y\B\F\\{CheckSum} \5
\\{int}\par
\Y\B\4\X4:Global \#\&{include}s\X${}\E{}$\6
\8\#\&{include} \.{<stdio.h>}\6
\8\#\&{include} \.{<ctype.h>}\6
\8\#\&{if} ${}\\{defined}(\.{\_\_STDC\_\_})\W\R\\{defined} \5(\.{\_\_GNUC\_%
\_}){}$\6
\8\#\&{include} \.{<stddef.h>}\6
\8\#\&{include} \.{<stdlib.h>}\6
\8\#\&{else}\6
\8\#\&{ifndef} \.{SEEK\_SET}\6
\8\#\&{define} \.{SEEK\_SET} \5\T{0}\6
\8\#\&{endif}\6
\8\#\&{endif}\6
\8\#\&{include} \.{<string.h>}\6
\8\#\&{ifdef} \.{THINK\_C}\6
\8\#\&{include} \.{<console.h>}\6
\8\#\&{endif}\6
\8\#\&{ifndef} \.{EXIT\_SUCCESS}\6
\8\#\&{define} \.{EXIT\_SUCCESS} \5\T{0}\6
\8\#\&{endif}\6
\8\#\&{ifndef} \.{EXIT\_FAILURE}\6
\8\#\&{define} \.{EXIT\_FAILURE} \5\T{1}\6
\8\#\&{endif}\6
\8\#\&{if} ${}\\{defined}(\.{\_\_STDC\_\_})\V\\{defined}(\.{\_\_GNUC\_\_})\V%
\\{defined}(\.{\_\_TURBOC\_\_})\V\\{defined} \5(\.{MSDOS}){}$\6
\8\#\&{define} \.{ARGS}(\\{plist}) \5\\{plist}\6
\8\#\&{else}\6
\8\#\&{define} \.{ARGS}(\\{plist}) \5(\,)\6
\8\#\&{endif}\6
\&{CheckSum}  \\{add\_a\_byte\_to\_checksum}\.{ARGS} ( ( \&{unsigned} \&{int} %
\\{new\_byte}${},{}$ \1\1 \&{CheckSum} \\{oldCheckSum} ) )  ;\6
\&{int}  \\{critical}\.{ARGS} ( (\&{char} ${}{*}\|s)$ )  ; \&{int}  \\{main}%
\.{ARGS} ( ( \&{int} \\{argc}${},{}$ \1\1 \&{char} ${}{*}{*}\\{argv}$ ) )  ;\6
\&{CheckSum}  \\{merge\_three\_checksums}\.{ARGS} ( ( \&{CheckSum} \|s${},{}$ %
\1\1 \&{CheckSum} \|t${},{}$ \1\1 \&{CheckSum} \|u ) )  ; \&{CheckSum}  %
\\{MultiplyTwoPolys}\.{ARGS} ( ( \&{CheckSum} \|u${},{}$ \1\1 \&{CheckSum} \|v
) )  ;\6
\&{unsigned} \&{long} \&{int}  \\{word\_count}\.{ARGS} ( (\&{char} ${}{*}\|s)$
)  ;\par
\U3.\fi

\M5. Now we come to the general layout of the \\{main} function.  The
\\{status} variable communicates to the operating system if the run was
successful or not, and \\{prog\_name} is used in case there's an error message
to
be printed.

\Y\B\4\D$\.{OK}$ \5
\T{0}\par
\B\4\D$\\{usage\_error}$ \5
\T{1}\par
\B\4\D$\\{cannot\_open\_read\_file}$ \5
\T{2}\par
\B\4\D$\\{cannot\_open\_write\_file}$ \5
\T{4}\par
\B\4\D$\\{error\_reading\_input\_file}$ \5
\T{8}\par
\B\4\D$\\{cannot\_open\_temporary\_file}$ \5
\T{16}\par
\Y\B\4\X5:Global variables\X${}\E{}$\6
\&{int} \\{status}${}\K\.{OK}{}$;\C{ exit status of command }\6
\&{char} ${}{*}\\{prog\_name}{}$;\par
\As14\ET56.
\U3.\fi

\M6. \B\X6:Main\X${}\E{}$\6
\&{int} ${}\\{main}(\\{argc},\39\\{argv}){}$\1\1\6
\&{int} \\{argc};\6
\&{char} ${}{*}{*}\\{argv};$ $\{$ \X7:Variables local to \\{main}\X\6
\8\#\&{ifdef} \.{THINK\_C}\6
\\{argc}${}\K\\{ccommand}({\AND}\\{argv});{}$\6
\8\#\&{endif}\6
${}\\{prog\_name}\K\\{argv}[\T{0}];$ \X8:Parse the command\X\6
\X66:Open the input and output files\X\6
\X13:Process the input file\X\6
\X32:Do endgame procedures\X\6
\&{if} ${}(\\{mode}\E\.{COMPUTING}){}$\5
${}\{\X31:Do second pass on input file\X\}{}$\6
\X69:Close all files\X\6
\&{if} ${}(\\{status}\I\T{0}){}$ \1\\{exit}(\.{EXIT\_FAILURE});\2\6
\&{else} \1${}\\{exit}(\\{verify\_successful}\?\.{EXIT\_SUCCESS}:\.{EXIT%
\_FAILURE});{}$\2\6
\&{return} (\T{0}); $\}{}$\par
\U3.\fi

\N7.  Parsing the command line.

We will have a variable \\{mode} which is set to indicate
whether we are ``computing'' or ``verifying'' the checksum.
\Y\B\4\D$\.{VERIFY}$ \5
\T{0}\par
\B\4\D$\.{COMPUTING}$ \5
\T{1}\par
\Y\B\4\X7:Variables local to \\{main}\X${}\E{}$\6
\&{int} \\{mode}${}\K\.{COMPUTING}{}$;\par
\As12, 22, 34, 37, 41, 44, 46, 50\ETs65.
\U6.\fi

\M8. The mode will be \.{VERIFY} iff the variable \\{argc} is $\geq 2$ and
the second ``argument'' is \.{"-v"}. In any case we should have \\{argc}
$\leq 3$. We update \\{argc} and \\{argv} to reflect the arguments already
``consumed''.
\Y\B\4\X8:Parse the command\X${}\E{}$\6
\&{if} ${}(\\{argc}>\T{3}){}$\5
${}\{\X71:Complain about improper command format\X\}{}$\5
\&{else} \1\&{if} ${}((\\{argc}\G\T{2})\W\R(\\{strcmp}(\\{argv}[\T{1}],\39%
\.{"-v"}))){}$\5
${}\{{}$\1\6
${}\\{mode}\K\.{VERIFY};{}$\6
${}\\{argc}\mathrel{-{\K}}\T{2};{}$\6
${}\\{argv}\mathrel{+{\K}}\T{2};{}$\6
\4${}\}{}$\2\6
\&{else} ${}\{{}$\1\6
${}\\{argc}\MM;{}$\6
${}\\{argv}\PP;{}$\6
\4${}\}{}$\2\2\par
\U6.\fi

\N9.  The main  loop.


Our main loop reads a line at a time from the input file.
It looks
for the ``critical line'' which first contains the word ``checksum''
(and no other alphabetic characters).

Suppose first that we are in \.{VERIFY} mode. As the program reads each
line, it updates its various counts (\\{lc}, \\{wc}, and \\{cc}) as well as
computing the checksum. When we encounter the critical line, we have
to record its predictions as to our counts and checksum, to compare
with those that are computed directly from the file. In addition, we
have to modify the line (as discussed above) replacing the checksum by
the string \.{"ZZZZZ"} before using the line in our checksum calculations.

Our processing of the input file will end when we reach an end of
file.
At that point, we compare the predicted counts and checksums with
those that are recorded on the critical line, and make a report to
\\{stdout} as to whether or not the verification was successful.

\fi

\M10.

Next we describe the main loop when we are in \.{COMPUTING} mode. As we
read each line, we see if it is the critical line or not. The first
phase of our operations consists of the processing of those lines
before the critical line. We update our counts and checksum. In
addition, we write each line as we read it out to the output file.

When we reach
the critical line, we store it in a special string buffer
\\{critical\_line}. We also record our place in the input file, so that
we will be able on our second pass to write the remainder of the input
file to the output file. (We must modify the critical line before
writing it to the output file so as to contain the counts and
checksum. We will only be able to compute these at the end of the
first pass through the input file.) The place in the input file that
we record will be directly after the critical line.

After
processing the remainder of the file, we will be able to correctly
compute the version of the critical line to write to the output file,
and we will be able to write the remainder of the input file to the
output file.

\fi

\M11.
We want to have a special type which is the kind of variable used for
accumulating checksums. The reason is that if we wish to change to a
32-bit checksum, it is useful to have just one definition to change.
\Y\B\4\D$\.{SIZE}$ \5
\T{16}\par
\Y\B\4\X11:Global type definitions\X${}\E{}$\6
\&{typedef} \&{unsigned} \&{int} \&{CheckSum};\par
\U3.\fi

\M12.
Here are the basic variables needed to accumulate the various counts,
etc.

The reasons for the mysterious initializations of the checksum
variables will become apparent below when we discuss the ``theory'' of
our device for doing the checksum calculation in one pass through the
input file.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{unsigned} \&{long} \&{int} \\{lc}${}\K\T{0}{}$;\C{line count}\6
\&{unsigned} \&{long} \&{int} \\{wc}${}\K\T{0}{}$;\C{ word count}\6
\&{unsigned} \&{long} \&{int} \\{cc}${}\K\T{0}{}$;\C{character count}\6
\&{int} \\{current\_line\_is\_critical};\C{ This flag is set to 1 if the
current                                line is the critical line}\6
\&{int} \\{found\_critical\_line}${}\K\T{0}{}$;\C{This flag is set to 1 after
the                               critical line is located.     }\6
\&{CheckSum} \\{chksum}${}\K\T{0},{}$ \\{auxchksum}${}\K\T{0},{}$ %
\\{auxchksum2}${}\K\T{1};{}$\6
\&{long} \&{int} \\{loc\_critical\_line};\C{This stores the location needed to
			rewind to the start of the line after the critical 			line in the input
file}\6
\&{int} \\{answer\_from\_critical}${}\K\T{0};{}$\6
\&{char} \\{current\_line}[\T{257}];\6
\&{char} \\{critical\_line}[\T{257}];\par
\fi

\M13. Here we read in the next line. If the pointer returned by \\{fgets} is
null, it might signal an \.{EOF} or it might be an error condition. We
use the \\{feof} facility to determine which. If it is an error
condition, we signal the error and abort the program. (If not, we are
done reading the input file, and the module \.{<Do endgame procedures>}
will take over.)

If the critical line has not yet been encountered, we must first check
if the current line is the critical line. If it is, we set two flags.
The first tells us that the critical line has indeed been found. The
second tells us that the current line  is indeed the critical line.
(This second flag must be set to 0 before we test for the critical
line.)


\Y\B\4\X13:Process the input file\X${}\E{}$\6
\&{while} ${}(\\{fgets}(\\{current\_line},\39\T{257},\39\\{input\_file})\I%
\NULL{}$)\6
$\{$ $\\{current\_line\_is\_critical}\K\T{0}{}$;\C{Reset this flag.}\6
\&{if} ${}(\\{found\_critical\_line}\E\T{0}){}$\1\5
\X20:Check if current line is critical line and set flags appropriately\X\2\6
\&{if} (\\{current\_line\_is\_critical})  $\{\X21:Process critical line\X\}{}$\6
\X25:Write line to output file if appropriate\X\6
\X26:Update counts\X\6
\X28:Update checksums\X\6
$\}{}$\6
\&{if} ${}(\R\\{feof}(\\{input\_file}))$ \X75:Signal error while reading input
file and abort\X\par
\U6.\fi

\M14. In order to check whether or not a line is critical, we use an
auxiliary function \\{critical}. This function returns a positive
integer  if the
line is critical and $0$ if it isn't.
The input to \\{critical} is a
pointer to the string that contains the current line.

If the line is critical, the function will set the value of the global
variable \\{loc\_chksum} to indicate the position of the word
\.{"checksum"} in the critical line. Then it will
search the portion of the
string after the word \.{"checksum"} for an occurrence of the string
\.{"\ =\ \\""}. If it doesn't find this string, it sets the return value of
\\{critical}
to 1 and exits. If it does, it records the position of the quote
character of the string in
the global variable \\{loc\_first\_quote\_mark}. It then proceeds to look
in the critical line
for a quote character occurring  after this string. If it doesn't
find this, the function returns 2; if it does, it stores its location
in the global variable \\{loc\_second\_quote\_mark} and returns the value
3.
\Y\B\4\X5:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{loc\_chksum}${},{}$ \\{loc\_first\_quote\_mark}${},{}$ \\{loc%
\_second\_quote\_mark};\par
\fi

\M15.
\Y\B\4\X15:All functions\X${}\E{}$\6
\&{int} \\{critical}(\|s)\1\1\6
\&{char} ${}{*}\|s;$ $\{{}$\X16:Variables for ``critical''\X\6
\X17:Code for ``critical''\X\6
${}\}{}$\par
\As27, 57, 60, 61, 62\ETs63.
\U3.\fi

\M16.

The variable \|i is a state variable which takes a value in the range
$0 \leq i \leq 3$. The precise meaning of the different states will be
explained below.

The variable $j$ holds our current place in the ``input string'' \|s.
Thus we usually refer to \|s[\|j] in the code that follows.

The array of characters \\{chksm} holds the string \.{"checksum"}.

The
variable $k$ holds our place in this string.

The variable $jj$ holds the location of the first character of the
string \.{"checksum"}
in the ``input string''.
\Y\B\4\X16:Variables for ``critical''\X${}\E{}$\6
\&{int} \|i${}\K\T{0};{}$\6
\&{int} \|j${}\K\T{0};{}$\6
\&{char} ${}{*}\\{chksm}\K\.{"checksum"};{}$\6
\&{int} \|k${}\K\T{0};{}$\6
\&{int} \\{jj};\par
\U15.\fi

\M17. We first determine if the string we are inspecting is the critical
line. If it is not, we bail out and return 0. If it is we set the
global variable \\{loc\_chksum} and continue.
As we read through the string \|s during this first phase, we are in
one of four states: We are in state $i=0$ until we have spotted the
first alphabetic character.

We are in state $i=1$ if we know definitely that the string we are
looking at is not critical.

We are in state $i=2$ while we are checking that the part of the
string we are now looking at is an occurrence of the word
``checksum''.

After we have seen the occurrence of the word ``checksum'' we are in
state 3.

\Y\B\4\X17:Code for ``critical''\X${}\E{}$\6
\&{while} ${}((\|i\I\T{1})\W(\|s[\|j]\I\T{0})){}$\1\6
\&{switch} (\|i)\5
${}\{{}$\1\6
\4\&{case} \T{0}:\6
\&{if} (\\{isalpha}(\|s[\|j]))\5
${}\{{}$\1\6
${}\|i\K\T{2};{}$\6
${}\\{jj}\K\|j;{}$\6
\4${}\}{}$\2\6
\&{else} \1${}\|j\PP;{}$\2\6
\&{break};\6
\4\&{case} \T{2}:\6
\&{if} ${}(\|s[\|j]\E\\{chksm}[\|k]){}$\5
${}\{{}$\1\6
${}\|k\PP;{}$\6
${}\|j\PP;{}$\6
\&{if} ${}(\|k\E\T{8}){}$\1\5
${}\|i\K\T{3};{}$\2\6
\4${}\}{}$\2\6
\&{else} \1${}\|i\K\T{1};{}$\2\6
\&{break};\6
\4\&{case} \T{3}:\6
\&{if} (\\{isalpha}(\|s[\|j]))\1\5
${}\|i\K\T{1};{}$\2\6
\&{else} \1${}\|j\PP;{}$\2\6
\&{break};\6
\4${}\}{}$\C{end switch}\2\2\6
\&{if} ${}(\|i\I\T{3}){}$\1\5
\&{return} (\T{0});\2\6
${}\\{loc\_chksum}\K\\{jj}{}$;\par
\As18\ET19.
\U15.\fi

\M18.
We next proceed to look for the string \.{"\ =\ \\""}. We search for the
final quote character of this string. If we find it, we check if the
preceding characters match up too. In this part of the code, we use
\|i as a flag which we set to one when we find the pattern we are
looking for.
\Y\B\4\X17:Code for ``critical''\X${}\mathrel+\E{}$\6
${}\|j\K\\{jj}+\T{8};{}$\6
${}\|i\K\T{0}{}$;\6
\&{while} ${}(\|s[\|j]\I\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|s[\|j]\I\.{'"'}){}$\5
${}\{{}$\1\6
${}\|j\PP;{}$\6
\&{continue};\6
\4${}\}{}$\2\6
\&{if} ${}((\|s[\|j-\T{1}]\E\.{'\ '})\W(\|s[\|j-\T{2}]\E\.{'='})\W(\|s[\|j-%
\T{3}]\E\.{'\ '})){}$\5
${}\{{}$\1\6
${}\\{loc\_first\_quote\_mark}\K\|j;{}$\6
${}\|i\K\T{1};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{else} \1${}\|j\PP;{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|i\E\T{0}){}$\1\5
\&{return} (\T{1});\2\par
\fi

\M19.
In this part of the code, we are looking for the second ``quote
mark''.
\Y\B\4\X17:Code for ``critical''\X${}\mathrel+\E{}$\6
${}\|j\PP;{}$\6
${}\|i\K\T{0};{}$\6
\&{while} ${}(\|s[\|j]\I\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|s[\|j]\E\.{'"'}){}$\5
${}\{{}$\1\6
${}\|i\K\T{1};{}$\6
${}\\{loc\_second\_quote\_mark}\K\|j;{}$\6
\&{break};\6
\4${}\}{}$\2\6
${}\|j\PP;{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\|i\E\T{0}){}$\1\5
\&{return} (\T{2});\2\6
\&{else} \1\&{return} (\T{3});\2\par
\fi

\M20. We stash the answer from the function \\{critical} away for future
use. Note that once the answer is positive, we will never call this
function again (because the flag \\{found\_critical\_line} will be set.
\Y\B\4\X20:Check if current line is critical line and set flags appropriately%
\X${}\E{}$\6
\&{if} ${}(\\{answer\_from\_critical}\K\\{critical}(\\{current\_line})){}$\1\5
${}\\{current\_line\_is\_critical}\K\\{found\_critical\_line}\K\T{1}{}$;\2\par
\U13.\fi

\M21. The flag \\{input\_from\_pipe} is set to $1$ if we are getting our input
from \\{stdin}. In that case, it is not possible to save our location in
the input file. Instead, we will store the remainder of the input file
to a temporary file and read that during the second pass.
\Y\B\4\X21:Process critical line\X${}\E{}$\6
$\{$ $\\{strcpy}(\\{critical\_line},\39\\{current\_line});$ \6
\&{if} ${}((\\{mode}\E\.{COMPUTING})\W\R\\{input\_from\_pipe}){}$\5
${}\{\X24:Store current location in input file\X\}{}$\6
\&{else}  \&{if} ${}(\\{mode}\E\.{VERIFY})$ $\{\X23:Adjust current line\X\}{}$\6
$\}{}$\par
\U13.\fi

\M22.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{int} \|i;\par
\fi

\M23.
\Y\B\4\X23:Adjust current line\X${}\E{}$\6
\&{for} ${}(\|i\K\T{1};{}$ ${}\|i<\T{6};{}$ ${}\|i\PP){}$\1\5
${}\\{current\_line}[\\{loc\_first\_quote\_mark}+\|i]\K\.{'Z'}{}$;\2\par
\U21.\fi

\M24.
\Y\B\4\X24:Store current location in input file\X${}\E{}$\6
${}\\{loc\_critical\_line}\K\\{ftell}(\\{input\_file}){}$;\par
\U21.\fi

\M25.
We write the current line to the output file if it is before the
critical line. If our input is from \\{stdin}, then we are unable to
rewind the ``input file'' for the second pass. We therefore copy out
the remainder of the input file to a temporary file.
\Y\B\4\X25:Write line to output file if appropriate\X${}\E{}$\6
\&{if} ${}(\\{mode}\E\.{COMPUTING}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{found\_critical\_line}){}$\1\5
${}\\{fputs}(\\{current\_line},\39\\{output\_file});{}$\2\6
\&{else} \1\&{if} ${}((\\{input\_from\_pipe})\W\R(\\{current\_line\_is%
\_critical})){}$\1\5
${}\\{fputs}(\\{current\_line},\39\\{temp\_file});{}$\2\2\6
\4${}\}{}$\2\par
\U13.\fi

\M26.
This section updates the various counts. The word count needs a
``home-grown'' function \\{word\_count} which we write next. If we are in
\.{COMPUTING} mode, we postpone the calculations for the ``critical
line''; they will be handled in the ``end-game'' procedures below.
\Y\B\4\X26:Update counts\X${}\E{}$\6
\&{if} ${}(\R(\\{current\_line\_is\_critical})\V(\\{mode}\E\.{VERIFY})){}$\5
${}\{{}$\1\6
${}\\{lc}\PP;{}$\6
${}\\{cc}\mathrel{+{\K}}\\{strlen}(\\{current\_line});{}$\6
${}\\{wc}\mathrel{+{\K}}\\{word\_count}(\\{current\_line});{}$\6
\4${}\}{}$\2\par
\U13.\fi

\M27.

\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{unsigned} \&{long} \&{int} \\{word\_count}(\|s)\1\1\6
\&{char} ${}{*}\|s{}$;\2\2\6
${}\{{}$\1\6
\&{int} \|i;\6
\&{int} \\{in\_word}${}\K\T{0};{}$\6
\&{int} \\{word\_cnt}${}\K\T{0};{}$\6
\&{char} \|c;\7
\&{for} ${}(\|i\K\T{0};{}$ ${}(\|s[\|i]\I\T{0})\W(\|s[\|i]\I\.{'\\n'});{}$ ${}%
\|i\PP){}$\5
${}\{{}$\1\6
${}\|c\K\|s[\|i];{}$\6
\&{if} ${}(\|c>\.{'\ '}\W\|c<\T{\~177}){}$\5
${}\{{}$\C{visible ASCII codes }\1\6
\&{if} ${}(\R\\{in\_word}){}$\5
${}\{{}$\1\6
${}\\{word\_cnt}\PP;{}$\6
${}\\{in\_word}\PP;{}$\6
\4${}\}{}$\2\6
\&{continue};\6
\4${}\}{}$\2\6
\&{if} ${}(\|c\I\.{'\ '}\W\|c\I\.{'\\t'}){}$\1\5
\&{continue};\2\6
${}\\{in\_word}\K\T{0};{}$\6
\4${}\}{}$\2\6
\&{return} ((\&{unsigned} \&{long} \&{int}) \\{word\_cnt});\6
\4${}\}{}$\2\par
\fi

\M28.

Our checksum can be computed ``a byte at a time''. Thus if the
sequence of bytes in the file is $s_0, s_1, \ldots, s_r$ (where the
$s_i$'s are all of type \&{unsigned} \&{char}, then the checksum will be the
value $t_{r+1}$ where the $t_i$'s are
computed inductively via the equations: $t_0 = 0$; $t_{j+1} =
\\{add\_a\_byte\_to\_checksum}(\hbox{$s_j,t_j$})$.

However, we are faced with the following problem. We don't know the
version of the ``critical line'' to be written to the output file
until we have read the whole file. It turns out that we can compute
two auxiliary checksums for the portion of the file that comes after
the critical line; when we reach the end of the file, we can compute
the output file version of the critical line, and then the checksum
for the portion of the file up to and including the critical line.
Then there is a simple procedure (to be explained below) which will
compute the checksum for the whole output file from these three
partial checksums.
\Y\B\4\X28:Update checksums\X${}\E{}$\6
\&{if} ${}(\\{mode}\E\.{VERIFY}\V\R\\{found\_critical\_line}){}$\5
${}\{\X29:Update one checksum\X\}{}$\6
\&{else}  \&{if} ${}(\R\\{current\_line\_is\_critical})$ $\{\X30:Update two
checksums\X\}{}$\par
\U13.\fi

\M29.
\Y\B\4\X29:Update one checksum\X${}\E{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\\{current\_line}[\|i]\I\T{0};{}$ ${}\|i\PP{}$)\1%
\6
${}\\{chksum}\K\\{add\_a\_byte\_to\_checksum}{}$((\&{unsigned} \&{int}) %
\\{current\_line}[\|i]${},\39\\{chksum}){}$;\2\par
\U28.\fi

\M30.
\Y\B\4\X30:Update two checksums\X${}\E{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\\{current\_line}[\|i]\I\T{0};{}$ ${}\|i\PP{}$)\6
${}\{{}$\1\6
${}\\{auxchksum}\K\\{add\_a\_byte\_to\_checksum}{}$((\&{unsigned} \&{int}) %
\\{current\_line}[\|i]${},\39\\{auxchksum});{}$\6
${}\\{auxchksum2}\K\\{add\_a\_byte\_to\_checksum}{}$((\&{unsigned} \&{int}) %
\\{current\_line}[\|i]${},\39\\{auxchksum2});{}$\6
\4${}\}{}$\2\par
\U28.\fi

\M31. We here simply rewind the input
file to the place directly after we discovered the critical line and
write all the following lines to the output file. (If we are receiving
our input from \\{stdin}, then we ``rewind'' the temporary file and make
that the input file.) The revised version of the critical line has
already been written to the output file by the ``end-game'' portion of
the program.
\Y\B\4\X31:Do second pass on input file\X${}\E{}$\6
\&{if} ${}(\R\\{input\_from\_pipe}){}$\1\5
${}\\{fseek}(\\{input\_file},\39\\{loc\_critical\_line},\39\.{SEEK\_SET});{}$\2%
\6
\&{else} ${}\{{}$\1\6
\\{rewind}(\\{temp\_file});\6
\\{fclose}(\\{input\_file});\6
${}\\{input\_file}\K\\{temp\_file};{}$\6
\4${}\}{}$\2\6
\&{while} ${}(\\{fgets}(\\{current\_line},\39\T{257},\39\\{input\_file})\I%
\NULL){}$\1\5
${}\\{fputs}(\\{current\_line},\39\\{output\_file});{}$\2\6
\&{if} ${}(\R\\{feof}(\\{input\_file}))$ \X75:Signal error while reading input
file and abort\X\par
\U6.\fi

\N32.  Endgame procedures.

\Y\B\4\X32:Do endgame procedures\X${}\E{}$\6
\&{if} ${}(\\{mode}\E\.{COMPUTING}){}$\5
${}\{\X33:Do \.{COMPUTING} endgame procedures\X\}{}$\6
\&{else}  $\{\X51:Do \.{VERIFY} endgame procedures\X\}{}$\par
\U6.\fi

\M33.
\Y\B\4\X33:Do \.{COMPUTING} endgame procedures\X${}\E{}$\6
\X35:Split \\{critical\_line} into two strings\X\6
\X42:Install the dummy checksum into the critical line.\X\6
\X43:Compute the final line count and install it.\X\6
\X45:Compute the final word count and install it\X\6
\X47:Compute the final character count and install it\X\6
\X48:Compute the correct checksum and install it\X\6
\X49:Write the critical line to the output file\X\par
\U32.\fi

\M34.

A major part of the work of the \.{COMPUTING} endgame procedures is in
assembling the string which will be the ``critical line'' in the
output file. For this we need a bunch of auxiliary string buffers.

We can use the space that was previously used to hold the ``current
line'' and just use a pointer into this space for one of our temporary
buffers. We will also have a smaller temporary buffer \\{temp\_buf2}
which is used to assemble various ``count fields'' for inclusion in the
new version of the critical line.


\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{temp\_buf};{}$\6
\&{char} \\{temp\_buf2}[\T{17}];\par
\fi

\M35.
We will now split the critical line into two parts. Precisely how we
do this will depend on the value of \\{answer\_from\_critical}. But after
this is done, the beginning part of the line will be the buffer
\\{critical\_line}, ending in the four character string \.{"\ =\ \\""}. The
portion of the line that will follow the ``second quote'' will be in
the buffer \\{temp\_buf}.

We don't actually delete the right portion of the ``critical line''
from the buffer \\{critical\_line}. Instead, we simply store a null
character at the appropriate place.
\Y\B\4\X35:Split \\{critical\_line} into two strings\X${}\E{}$\6
${}\\{temp\_buf}\K\\{current\_line};$ \&{switch} (\\{answer\_from\_critical}) $%
\{{}$\par
\As36, 38, 39\ETs40.
\U33.\fi

\M36. The first case to consider is when \\{answer\_from\_critical} $=0$. This
case ``can't happen'' so we print an appropriate error message and
exit the program.
\Y\B\4\X35:Split \\{critical\_line} into two strings\X${}\mathrel+\E{}$\6
\&{case} \T{0}: $\{\X76:Issue complaint about the bad format of the input file%
\X\}{}$\6
\&{break};\par
\fi

\M37. For the second case, the line does not contain the pattern \.{"\ =\ \\""}
after the word \.{"checksum"}, We will put the portion of the critical
line after the word \.{"checksum"} in the buffer \\{temp\_buf}, and place
the string \.{"\ =\ \\""} after the end of the word \.{"checksum"} followed
by a null character.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{quote\_pattern}\K\.{"\ =\ \\""}{}$;\par
\fi

\M38.
\Y\B\4\X35:Split \\{critical\_line} into two strings\X${}\mathrel+\E{}$\6
\4\&{case} \T{1}:\5
${}\\{strcpy}(\\{temp\_buf},\39\\{critical\_line}+(\\{loc\_chksum}+\T{8}));{}$\6
${}\\{critical\_line}[\\{loc\_chksum}+\T{8}]\K\T{0};{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{quote\_pattern});{}$\6
${}\\{loc\_first\_quote\_mark}\K\\{loc\_chksum}+\T{11};{}$\6
\&{break};\par
\fi

\M39. The next case is when we can find the pattern \.{"\ =\ \\""} in the
critical line but not a following ``quote''. In that case, we split at
the quote mark of the pattern \.{"\ =\ \\""}.
\Y\B\4\X35:Split \\{critical\_line} into two strings\X${}\mathrel+\E{}$\6
\4\&{case} \T{2}:\5
${}\\{strcpy}(\\{temp\_buf},\39\\{critical\_line}+(\\{loc\_first\_quote\_mark}+%
\T{1}));{}$\6
${}\\{critical\_line}[\\{loc\_first\_quote\_mark}+\T{1}]\K\T{0};{}$\6
\&{break};\par
\fi

\M40. In the final case, we can find both the pattern \.{"\ =\ \\""} and a
following ``quote-mark''. We store the portion of the critical line
after the second ``quote-mark'' in \\{temp\_buf} and put a null character
in the buffer \\{critical\_line} after the first ``quote-mark''. This has
the effect of erasing the text that is between the two ``quote-marks''
in the input file. It will be replaced by the new checksum and counts
in the later portions of the program.
\Y\B\4\X35:Split \\{critical\_line} into two strings\X${}\mathrel+\E{}$\6
\4\&{case} \T{3}:\5
${}\\{strcpy}(\\{temp\_buf},\39\\{critical\_line}+(\\{loc\_second\_quote%
\_mark}+\T{1}));{}$\6
${}\\{critical\_line}[\\{loc\_first\_quote\_mark}+\T{1}]\K\T{0};{}$\6
\&{break}; $\}{}$\C{ end of switch}\par
\fi

\M41.
We will next insert the string \.{"ZZZZZ\ "} as part of the new
``critical line'' we are building. Later we will have to replace the
string \.{"ZZZZZ"} by the correct checksum.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{Zstring}\K\.{"ZZZZZ\ "};{}$\6
\&{char} ${}{*}\\{one\_space}\K\.{"\ "};{}$\6
\&{char} ${}{*}\\{quote}\K\.{"\\""}{}$;\par
\fi

\M42.
\Y\B\4\X42:Install the dummy checksum into the critical line.\X${}\E{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{Zstring}){}$;\par
\U33.\fi

\M43.
The installation of the final line count is easy. We have to increment
the line count by 1 for the ``critical line''.
\Y\B\4\X43:Compute the final line count and install it.\X${}\E{}$\6
${}\\{lc}\PP;{}$\6
${}\\{sprintf}(\\{temp\_buf2},\39\.{"\%lu"},\39\\{lc});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{temp\_buf2});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{one\_space}){}$;\par
\U33.\fi

\M44. Computing the final word count is slightly more involved. We will
add two dummy fields to the critical line and then tack on the text in
\\{temp\_buf}. We will take the ``word count'' of this line and add it to
\\{wc}.  Then we
erase the material we have added from the line, but add in the new
word count much as we added in the line count in the preceding module.
We need to keep track of our position in the line, wo we define a
variable in which to stash it.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{int} \\{loc\_in\_line};\6
\&{char} ${}{*}\\{dummy\_field\_pattern}\K\.{"B\ C\\""}{}$;\par
\fi

\M45.

\Y\B\4\X45:Compute the final word count and install it\X${}\E{}$\6
${}\\{loc\_in\_line}\K\\{strlen}(\\{critical\_line});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{dummy\_field\_pattern});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{temp\_buf});{}$\6
${}\\{wc}\mathrel{+{\K}}\\{word\_count}(\\{critical\_line});{}$\6
${}\\{critical\_line}[\\{loc\_in\_line}]\K\T{0};{}$\6
${}\\{sprintf}(\\{temp\_buf2},\39\.{"\%lu"},\39\\{wc});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{temp\_buf2});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{one\_space}){}$;\par
\U33.\fi

\M46.
The computation of the final character count involves an iterative
procedure. The problem is that the total character count includes the
number of characters in the character-count itself. A simple analysis
shows the process converges in at most three iterations. (The 1 in the
computation of \\{cc\_guess} comes from the length of the string \.{"\\""}.)

At the end of this module, we splice back the second half
of the critical line which we stashed in \\{temp\_buf}.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{int} \\{char\_field\_length}${}\K\T{0};{}$\6
\&{int} \\{old\_char\_field\_length};\6
\&{unsigned} \&{long} \&{int} \\{cc\_guess};\par
\fi

\M47.
\Y\B\4\X47:Compute the final character count and install it\X${}\E{}$\6
${}\\{cc}\mathrel{+{\K}}\\{strlen}(\\{temp\_buf})+\\{strlen}(\\{critical%
\_line});{}$\6
\&{do}\6
${}\{{}$\1\6
${}\\{cc\_guess}\K\\{cc}+\\{char\_field\_length}+\T{1};{}$\6
${}\\{sprintf}(\\{temp\_buf2},\39\.{"\%lu"},\39\\{cc\_guess});{}$\6
${}\\{old\_char\_field\_length}\K\\{char\_field\_length};{}$\6
${}\\{char\_field\_length}\K\\{strlen}(\\{temp\_buf2});{}$\6
\4${}\}{}$\2\6
\&{while} ${}(\\{old\_char\_field\_length}\I\\{char\_field\_length});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{temp\_buf2});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{quote});{}$\6
${}\\{strcat}(\\{critical\_line},\39\\{temp\_buf}){}$;\par
\U33.\fi

\M48.
The function \\{merge\_three\_checksums} does the computation of the final
checksum from the three partial checksums alluded to above.
\Y\B\4\X48:Compute the correct checksum and install it\X${}\E{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\\{critical\_line}[\|i]\I\T{0};{}$ ${}\|i\PP{}$)%
\1\6
${}\\{chksum}\K\\{add\_a\_byte\_to\_checksum}{}$((\&{unsigned} \&{int}) %
\\{critical\_line}[\|i]${},\39\\{chksum}){}$;\2\6
${}\\{chksum}\K\\{merge\_three\_checksums}(\\{chksum},\39\\{auxchksum},\39%
\\{auxchksum2});{}$\6
${}\\{sprintf}(\\{temp\_buf2},\39\.{"\%05u"},\39\\{chksum});{}$\6
${}\\{strncpy}(\\{critical\_line}+(\\{loc\_first\_quote\_mark}+\T{1}),\39%
\\{temp\_buf2},\39\T{5}){}$;\par
\U33.\fi

\M49.
\Y\B\4\X49:Write the critical line to the output file\X${}\E{}$\6
${}\\{fputs}(\\{critical\_line},\39\\{output\_file}){}$;\par
\U33.\fi

\M50.

The verify ``endgame procedures'' consist in comparing the various
computed counts and the checksum with those stored in the critical
lines. If everything checks out, we write a ``success'' message to
\\{stdout}; if not we write a ``failure'' message.

We need some variables to store the fields extracted from the critical
line. We also need a pointer to use in extracting these fields.


\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{unsigned} \&{long} \&{int} \\{stored\_wc}${}\K\T{0}{}$;\C{ stored word
count}\6
\&{unsigned} \&{long} \&{int} \\{stored\_cc}${}\K\T{0}{}$;\C{stored character
count}\6
\&{unsigned} \&{long} \&{int} \\{stored\_lc}${}\K\T{0}{}$;\C{stored line count}%
\6
\&{CheckSum} \\{stored\_chksum};\6
\&{int} \\{verify\_successful}${}\K\T{1};{}$\6
\8\#\&{if} \\{vms}\6
\&{char} ${}{*}\\{format}\K\.{"\%d\ \%ld\ \%ld\ \%ld"}{}$;\C{ VMS C sscanf()
doesn't support u item. }\C{ none of these numbers overflow into the }\C{ sign
bit on the VAX, so use %d instead }\6
\8\#\&{else}\6
\&{char} ${}{*}\\{format}\K\.{"\%u\ \%lu\ \%lu\ \%lu"};{}$\6
\8\#\&{endif}\6
\&{char} ${}{*}\\{position\_in\_line}{}$;\par
\fi

\M51. The first command positions the pointer \\{position\_in\_line} at the
start of the \\{chksum} field.
\Y\B\4\X51:Do \.{VERIFY} endgame procedures\X${}\E{}$\6
\&{if} ${}(\R\\{found\_critical\_line}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"The\ input\ file\ did\ }\)\.{not\ have\ the\ correct}\)\.{\
format.\\n"});\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\6
${}\\{position\_in\_line}\K\\{critical\_line}+\\{loc\_first\_quote\_mark}+%
\T{1};{}$\6
\&{if} ${}(\T{4}\I\\{sscanf}(\\{position\_in\_line},\39\\{format},\39{\AND}%
\\{stored\_chksum},\39{\AND}\\{stored\_lc},\39{\AND}\\{stored\_wc},\39{\AND}%
\\{stored\_cc})){}$\5
${}\{{}$\1\6
\\{printf}(\.{"The\ input\ file\ did\ }\)\.{not\ have\ the\ correct}\)\.{\
format.\\n"});\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\6
${}\\{verify\_successful}\K(\\{chksum}\E\\{stored\_chksum}\W\\{wc}\E\\{stored%
\_wc}\W\\{lc}\E\\{stored\_lc}\W\\{cc}\E\\{stored\_cc});{}$\6
\&{if} (\\{verify\_successful})\1\5
\\{printf}(\.{"The\ checksum\ verifi}\)\.{cation\ of\ the\ input\ }\)\.{file\
was\ successful.}\)\.{\\n"});\2\6
\&{else} \1\\{printf}(\.{"The\ checksum\ verifi}\)\.{cation\ of\ the\ input\ }%
\)\.{file\ did\ not\ succeed}\)\.{.\\n"});\2\par
\U32.\fi

\N52.  CRC checksums.

In computing the checksum of the file {\sl outputfile} as
discussed above, we run into the following problem. We will only know
the various counts (such as the word count) after reading the whole
file. A naive implementation of the program would require three passes
through the input file: (1) A pass through the file to compute the
word, character, and line counts. (2) A pass through the file to
compute the CRC-16 checksum. (3) A final pass to copy the input file
to the output file.

However, we will be able to get by with only two  passes through the input
file because of the following feature of the CRC-checksum. Let $s_1$
be a string of bytes with the checksum $c_1$. Let $s_2$ be a string of
bytes, and let $s$ be the concatenation of $s_1$ and $s_2$ in that
order, and let $c$ be the checksum of $s$. Then we will be able to
compute from $s_2$ two summary numbers $a_2$ and $c_2$ (where $c_2$ is
the usual checksum for $s_2$, and $a_2$ is also an integer such that
$0 \leq a_2 < 2^{16}$) such that $c$ can be quickly computed from
$c_1$, $c_2$, and $a_2$.

In this section of the program, we develop the ideas needed to verify
the property of CRC checksums just stated, and write the code for the
various functions needed to compute CRC checksums.

\fi

\M53.

For an excellent discussion of the ideas involved in the CRC checksum,
we refer the reader to the paper {\sl A Tutorial in CRC Computations}
by
T.~V.~Ramabadran and S.~S.~Gaitonde which appeared in IEEE Micro vol.
8, no. 4, (August 1988), pp. 62--75.

\def\Zt{{\bf Z}_2}

$\Zt$ is the two element field. $\Zt[X]$ is the ring of polynomials
in the variable $X$
with coefficients in the field $\Zt$. A crucial role in the CRC-16
algorithm is played by the polynomial $p(X) = X^{16} + X^{15} + X^2 +
1$.

We let $R$ be the quotient ring obtained by dividing $\Zt[X]$ by the
ideal generated by the polynomial $p$. Then $R$ has cardinality
$2^{16}$. Clearly each element of $R$ lies in the same equivalence
class as a unique polynomial of $\Zt[X]$ of degree less than $16$, and
in this way, we identify $R$ with the set of polynomials of degree
less than $16$.

We associate to each integer $x$ such that $0 \leq x < 256$ a
polynomial in $\Zt[X]$ of degree at most $7$ as follows. Let
$a_7\ldots a_0$ be the binary expansion of $x$ (so $0 \leq a_i < 2$
for $0 \leq i < 7$ and $x = \sum_{i=0}^7 a_i 2^i$. Then the polynomial
associated to $x$ is $\sum_{i=0}^7 a_i X^i$.

\fi

\M54. Now consider a string of bytes $s_0\ldots s_r$. (Here the $s_i$'s
may be viewed as integers in the range $0 \leq s_i < 256$. We wish to
associate to this sequence an element of $R$ which will be its
checksum.

We do this as follows. Let $p_i$ be the polynomial associated to $s_i$
as discussed in the preceding paragraph. Let $p$ be the polynomial
$\sum_{i=0}^r p_i X^{8(r-i)}$. There is a canonical homomorphism of
$\Zt[X]$ onto $R$. The checksum of the sequence $s_0\ldots s_r$ is the
image of $p$ in $R$.

The following way of looking at $p$ may make its definition seem more
natural. View the string of $r+1$ bytes $s_0\ldots s_r$ as a string of
$8(r+1)$ bits $b_0 \ldots b_{8r+7}$ by replacing each byte $s_i$ by
its binary expansion $s_{i,7} \ldots s_{i,0}$. To this string of bits
we associate the polynomial $\sum_{i=0}^{8r+7} b_i X^{(8r + 7) - i}$.

This allows the following inductive definition of the checksum. Let
$t_0 = 0$. Let $t_{i+1}$ be the canonical image in $R$ of $X^8 \cdot
t_i + p_{i+1}$. Then $t_{i+1}$ is easily checked to be the checksum of
the sequence $s_0 \ldots s_i$.

\fi

\M55. We can identify $R$ with the set of integers $x$ such that $0 \leq x
< 2^{16}$ as follows. Let $r \in R$. Then $r$ is the image of a unique
polynomial of degree at most 15 in $\Zt[X]$, say $\sum_{i=0}^{15} a_i
X^i$. We identify $r$ with the integer $\sum_{i=0}^{15} a_i 2^i$.

Suppose then that $r \in R$ and that $s$ is an unsigned byte. We wish
to indicate how we will implement a function that will quickly compute
the element of $R$ that corresponds to $X^8 \cdot r + s$.

The first point to make is that via our identification of $R$ with
unsigned integers in the range $0 \leq x < 2^{16}$, the operation of
addition in $R$ corresponds to the bit-wise exclusive {\sl or\/} (rendered in
C as $\XOR$).

Second, if we write a typical element $r$ in $R$ as a polynomial of
degree less than $16$ in $\Zt[X]$, and then write this polynomial as
$r_1 X^8 + r_2$ where $r_1$ and $r_2$ are polynomials of degree at
most $7$ in $\Zt[X]$, then $r_1$ and $r_2$ correspond respectively to
the high-order byte and low-order byte of the unsigned integer
corresponding to $r$.

We will precompute a table \\{crc\_table}[\|i] (where $0 \leq i < 256$ such
that if $p$ is the polynomial of degree at most $7$ corresponding to
$i$, then $\\{crc\_table}[i]$ gives the unsigned integer corresponding to
the element of $R$ which is the homomorphic image of $X^{16}\cdot p$.

In these terms, if we add the byte \\{new\_byte} to the \\{old\_checksum} wth
high-order byte $r_1$ and low order byte $r_2$, the resulting
element of $R$ will be $\\{crc\_table}(r_1) + X^8\cdot r_2 + \\{new\_byte}$.
To complete the explanation of the code that follows we need merely
note that the operation of multiplying by $X^8$ corresponds to a left
shift by 8 bits.
\fi

\M56.
We now begin writing the code for the \\{add\_a\_byte\_to\_checksum}
function. A key role is played by the following table. This table is
computed in the program described in the CWeb file {\tt polynom.w}
which is enclosed with this distribution.
\Y\B\4\X5:Global variables\X${}\mathrel+\E{}$\6
\&{static} \&{CheckSum} \\{crc\_table}[\,]${}\K\{\T{\^0000},\39\T{\^8005},\39%
\T{\^800f},\39\T{\^000a},\39\T{\^801b},\39\T{\^001e},\39\T{\^0014},\39\T{%
\^8011},\39\T{\^8033},\39\T{\^0036},\39\T{\^003c},\39\T{\^8039},\39\T{\^0028},%
\39\T{\^802d},\39\T{\^8027},\39\T{\^0022},\39\T{\^8063},\39\T{\^0066},\39\T{%
\^006c},\39\T{\^8069},\39\T{\^0078},\39\T{\^807d},\39\T{\^8077},\39\T{\^0072},%
\39\T{\^0050},\39\T{\^8055},\39\T{\^805f},\39\T{\^005a},\39\T{\^804b},\39\T{%
\^004e},\39\T{\^0044},\39\T{\^8041},\39\T{\^80c3},\39\T{\^00c6},\39\T{\^00cc},%
\39\T{\^80c9},\39\T{\^00d8},\39\T{\^80dd},\39\T{\^80d7},\39\T{\^00d2},\39\T{%
\^00f0},\39\T{\^80f5},\39\T{\^80ff},\39\T{\^00fa},\39\T{\^80eb},\39\T{\^00ee},%
\39\T{\^00e4},\39\T{\^80e1},\39\T{\^00a0},\39\T{\^80a5},\39\T{\^80af},\39\T{%
\^00aa},\39\T{\^80bb},\39\T{\^00be},\39\T{\^00b4},\39\T{\^80b1},\39\T{\^8093},%
\39\T{\^0096},\39\T{\^009c},\39\T{\^8099},\39\T{\^0088},\39\T{\^808d},\39\T{%
\^8087},\39\T{\^0082},\39\T{\^8183},\39\T{\^0186},\39\T{\^018c},\39\T{\^8189},%
\39\T{\^0198},\39\T{\^819d},\39\T{\^8197},\39\T{\^0192},\39\T{\^01b0},\39\T{%
\^81b5},\39\T{\^81bf},\39\T{\^01ba},\39\T{\^81ab},\39\T{\^01ae},\39\T{\^01a4},%
\39\T{\^81a1},\39\T{\^01e0},\39\T{\^81e5},\39\T{\^81ef},\39\T{\^01ea},\39\T{%
\^81fb},\39\T{\^01fe},\39\T{\^01f4},\39\T{\^81f1},\39\T{\^81d3},\39\T{\^01d6},%
\39\T{\^01dc},\39\T{\^81d9},\39\T{\^01c8},\39\T{\^81cd},\39\T{\^81c7},\39\T{%
\^01c2},\39\T{\^0140},\39\T{\^8145},\39\T{\^814f},\39\T{\^014a},\39\T{\^815b},%
\39\T{\^015e},\39\T{\^0154},\39\T{\^8151},\39\T{\^8173},\39\T{\^0176},\39\T{%
\^017c},\39\T{\^8179},\39\T{\^0168},\39\T{\^816d},\39\T{\^8167},\39\T{\^0162},%
\39\T{\^8123},\39\T{\^0126},\39\T{\^012c},\39\T{\^8129},\39\T{\^0138},\39\T{%
\^813d},\39\T{\^8137},\39\T{\^0132},\39\T{\^0110},\39\T{\^8115},\39\T{\^811f},%
\39\T{\^011a},\39\T{\^810b},\39\T{\^010e},\39\T{\^0104},\39\T{\^8101},\39\T{%
\^8303},\39\T{\^0306},\39\T{\^030c},\39\T{\^8309},\39\T{\^0318},\39\T{\^831d},%
\39\T{\^8317},\39\T{\^0312},\39\T{\^0330},\39\T{\^8335},\39\T{\^833f},\39\T{%
\^033a},\39\T{\^832b},\39\T{\^032e},\39\T{\^0324},\39\T{\^8321},\39\T{\^0360},%
\39\T{\^8365},\39\T{\^836f},\39\T{\^036a},\39\T{\^837b},\39\T{\^037e},\39\T{%
\^0374},\39\T{\^8371},\39\T{\^8353},\39\T{\^0356},\39\T{\^035c},\39\T{\^8359},%
\39\T{\^0348},\39\T{\^834d},\39\T{\^8347},\39\T{\^0342},\39\T{\^03c0},\39\T{%
\^83c5},\39\T{\^83cf},\39\T{\^03ca},\39\T{\^83db},\39\T{\^03de},\39\T{\^03d4},%
\39\T{\^83d1},\39\T{\^83f3},\39\T{\^03f6},\39\T{\^03fc},\39\T{\^83f9},\39\T{%
\^03e8},\39\T{\^83ed},\39\T{\^83e7},\39\T{\^03e2},\39\T{\^83a3},\39\T{\^03a6},%
\39\T{\^03ac},\39\T{\^83a9},\39\T{\^03b8},\39\T{\^83bd},\39\T{\^83b7},\39\T{%
\^03b2},\39\T{\^0390},\39\T{\^8395},\39\T{\^839f},\39\T{\^039a},\39\T{\^838b},%
\39\T{\^038e},\39\T{\^0384},\39\T{\^8381},\39\T{\^0280},\39\T{\^8285},\39\T{%
\^828f},\39\T{\^028a},\39\T{\^829b},\39\T{\^029e},\39\T{\^0294},\39\T{\^8291},%
\39\T{\^82b3},\39\T{\^02b6},\39\T{\^02bc},\39\T{\^82b9},\39\T{\^02a8},\39\T{%
\^82ad},\39\T{\^82a7},\39\T{\^02a2},\39\T{\^82e3},\39\T{\^02e6},\39\T{\^02ec},%
\39\T{\^82e9},\39\T{\^02f8},\39\T{\^82fd},\39\T{\^82f7},\39\T{\^02f2},\39\T{%
\^02d0},\39\T{\^82d5},\39\T{\^82df},\39\T{\^02da},\39\T{\^82cb},\39\T{\^02ce},%
\39\T{\^02c4},\39\T{\^82c1},\39\T{\^8243},\39\T{\^0246},\39\T{\^024c},\39\T{%
\^8249},\39\T{\^0258},\39\T{\^825d},\39\T{\^8257},\39\T{\^0252},\39\T{\^0270},%
\39\T{\^8275},\39\T{\^827f},\39\T{\^027a},\39\T{\^826b},\39\T{\^026e},\39\T{%
\^0264},\39\T{\^8261},\39\T{\^0220},\39\T{\^8225},\39\T{\^822f},\39\T{\^022a},%
\39\T{\^823b},\39\T{\^023e},\39\T{\^0234},\39\T{\^8231},\39\T{\^8213},\39\T{%
\^0216},\39\T{\^021c},\39\T{\^8219},\39\T{\^0208},\39\T{\^820d},\39\T{\^8207},%
\39\T{\^0202},\}{}$;\par
\fi

\M57.

The following is the function definition for \\{add\_a\_byte\_to\_checksum}.


\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{CheckSum} ${}\\{add\_a\_byte\_to\_checksum}(\\{new\_byte},\39%
\\{oldCheckSum}){}$\1\1\6
\&{unsigned} \&{int} \\{new\_byte};\6
\&{CheckSum} \\{oldCheckSum};\2\2\6
${}\{{}$\1\6
\&{CheckSum} \|u;\7
${}\|u\K{}$(\&{CheckSum}) \\{new\_byte};\6
${}\\{oldCheckSum}\K\\{oldCheckSum}\AND\T{\^ffff};{}$\6
${}\|u\K((\\{oldCheckSum}\LL\T{8})\AND\T{\^ffff})\XOR\|u;{}$\6
${}\|u\K\|u\XOR\\{crc\_table}[(\\{oldCheckSum}\GG\T{8})\AND\T{\^ff}];{}$\6
\&{return} (\|u);\6
\4${}\}{}$\2\par
\fi

\M58. We next wish to indicate the trick that allows us to compute the
checksum in one pass through the input file rather than two.

First let $b$ be an unsigned char. Then $b$ determines a function
$f_b: R \to R$ as follows: $f_b(r) = X^8\cdot r + b$.

More generally let $a$ and $b$ be elements of $R$. Then these
determine a map $g_{a,b}:R \to R$ via the stipulation $$g_{a,b}(x) =
a\cdot x + b.$$

Let $G$ be the set of all maps from $R$ to $R$ obtained in this way
(for various choices of $a$ and $b$.) Then clearly $f_b$ is of this
form, and the collection of maps of this form is readily seen to be
closed under composition.

Let $g \in G$. Then $g$ is completely determined by the values of
$g(0)$ and $g(1)$. Indeed, $g(0)=b$ and $g(1)= a + b$. Remembering
that in $R$, $-1=1$, we see that $a = g(0) + g(1)$.

\fi

\M59. Our strategy for determining the checksum in one pass should now be
clear. Let $s_0,\ldots s_r$ be the sequence of bytes that correspond
to the lines of the output file up to and including the critical line.
Let $s_{r+1}\ldots s_t$ be the remaining bytes of the input file.
These will determine a function $g \in G$ such that if $c$ is the
checksum determined by $s_0\ldots s_r$, then $g(c)$ will be the
desired final checksum. To compute $g$ it suffices to compute $g(0)$
and $g(1)$. These are the numbers we are computing in the variables
\\{auxchksum} and \\{auxchksum2}.

It remains to derive the formula for $g(c)$ in terms of $c$,
$g(0)$, and $g(1)$. But this is easy. We know $g(c) = a \cdot c + b$
and $a= g(0) + g(1)$, $b = g(0)$. So $g(c) = c\cdot(g(0) + g(1)) + g(0)$.

\fi

\M60.
We need some code to multiply two polynomials in the ring $R$. Since
there will be precisely one such multiplication in the course of a run
of the program, we opt for straightforward coding rather than blinding
speed.

The first part of the code puts the $\Zt$ polynomial of degree at
most $31$ which is the product of the two $\Zt$ polynomials
corresponding to the inputs $u$ and $v$ in the array \\{w\_array} .
\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{CheckSum} ${}\\{MultiplyTwoPolys}(\|u,\39\|v){}$\1\1\6
\&{CheckSum} \|u${},{}$ \|v;\6
$\{$ \&{CheckSum} \|r${}\K\T{0};{}$\6
\&{int} \\{u\_array}[\.{SIZE}];\6
\&{int} \\{v\_array}[\.{SIZE}];\6
\&{int} ${}\\{w\_array}[\.{SIZE}+\.{SIZE}];{}$\6
\&{int} \|i${},{}$ \|j;\6
\&{CheckSum} \|s[\T{4}];\7
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\.{SIZE};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\\{u\_array}[\|i]\K\|u\MOD\T{2};{}$\6
${}\|u\K\|u/\T{2};{}$\6
${}\\{v\_array}[\|i]\K\|v\MOD\T{2};{}$\6
${}\|v\K\|v/\T{2};{}$\6
\4${}\}{}$\2\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<(\.{SIZE}+\.{SIZE});{}$ ${}\|i\PP){}$\1\5
${}\\{w\_array}[\|i]\K\T{0};{}$\2\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\.{SIZE};{}$ ${}\|i\PP){}$\1\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\.{SIZE};{}$ ${}\|j\PP){}$\1\5
${}\\{w\_array}[\|i+\|j]\mathrel{+{\K}}(\\{u\_array}[\|i]*\\{v\_array}[%
\|j]);{}$\2\2\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\.{SIZE}+\.{SIZE};{}$ ${}\|i\PP){}$\1\5
${}\\{w\_array}[\|i]\K\\{w\_array}[\|i]\MOD\T{2}{}$;\2\par
\fi

\M61.
Our next task is to store the array \\{w\_array} as an array of four
``bytes'', \|s[\T{4}].
\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\T{4};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\|s[\|i]\K\T{0};{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{8};{}$ ${}\|j\PP){}$\1\5
${}\|s[\|i]\K(\|s[\|i]*\T{2})+\\{w\_array}[(\T{8}*\|i)+(\T{7}-\|j)];{}$\2\6
\4${}\}{}$\2\par
\fi

\M62.
Finally we have to reduce this polynomial to one of degree at most 15
that is its canonical image in $R$. The table \\{crc\_table} has all the
needed information to do this expeditiously.
\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{for} ${}(\|i\K\T{3};{}$ ${}\|i>\T{1};{}$ ${}\|i\MM){}$\5
${}\{{}$\1\6
${}\|s[\|i-\T{1}]\K\|s[\|i-\T{1}]\XOR((\\{crc\_table}[\|s[\|i]]\GG\T{8})\AND\T{%
\^ff});{}$\6
${}\|s[\|i-\T{2}]\K\|s[\|i-\T{2}]\XOR((\\{crc\_table}[\|s[\|i]])\AND\T{%
\^ff});{}$\6
\4${}\}{}$\2\6
${}\|r\K(\|s[\T{1}]\LL\T{8})\XOR\|s[\T{0}];{}$\6
\&{return} (\|r); $\}{}$\par
\fi

\M63.

The motivation for the following function is contained in the
preceding discussion.

\Y\B\4\X15:All functions\X${}\mathrel+\E{}$\6
\&{CheckSum} ${}\\{merge\_three\_checksums}(\|s,\39\|t,\39\|u){}$\1\1\6
\&{CheckSum} \|s${},{}$ \|t${},{}$ \|u;\2\2\6
${}\{{}$\1\6
\&{CheckSum} \|w;\7
${}\|w\K\|t\XOR\|u;{}$\6
${}\|w\K\\{MultiplyTwoPolys}(\|w,\39\|s);{}$\6
\&{return} ${}(\|w\XOR\|t);{}$\6
\4${}\}{}$\2\par
\fi

\N64.  Input and output.

This section contains code concerned with opening and closing files.

\fi

\M65. We next have to open the input file (and if $\\{mode}\E\.{COMPUTING}$ the
output file). We will also need a pointer to a  temporary file.

We also will need a flag \\{input\_from\_pipe} which we will set to $1$ if
the input is coming from stdin.
\Y\B\4\X7:Variables local to \\{main}\X${}\mathrel+\E{}$\6
\&{FILE} ${}{*}\\{input\_file},{}$ ${}{*}\\{output\_file},{}$ ${}{*}\\{temp%
\_file};{}$\6
\&{int} \\{input\_from\_pipe}${}\K\T{0}{}$;\par
\fi

\M66. If the argument for the input file is missing or the string \.{"-"} is
used, then the input is taken from \\{stdin}. Simarly, if the argument
for the output file is missing or the string \.{"-"} is used, then the
output is sent to \\{stdout}.
\Y\B\4\X66:Open the input and output files\X${}\E{}$\6
\&{if} ${}(\\{argc}\E\T{0}){}$\5
${}\{\X68:Input file is stdin\X\}{}$\6
\&{else}\1\hbox{\quad}\5
\2\&{if} ${}(\R(\\{strcmp}(\\{argv}[\T{0}],\39\.{"-"}))){}$  $\{$ $\\{argc}%
\MM;{}$\6
${}\\{argv}\PP;$ $\{\X68:Input file is stdin\X\}$ $\}{}$\6
\hbox{\quad}\5
\&{else}\5
${}\{{}$\1\6
\&{if} ${}((\\{input\_file}\K\\{fopen}(\\{argv}[\T{0}],\39\.{"r"}))\E\NULL){}$\5
${}\{\X72:Handle error while opening input file\X\}{}$\6
\hbox{\quad\quad\quad\quad}\5
\&{else} ${}\{{}$\5
\1${}\\{argc}\MM;{}$\6
${}\\{argv}\PP{}$;\5
${}\}{}$\5
\2${}\}{}$\2\par
\A67.
\U6.\fi

\M67.
Now we open the output file.
\Y\B\4\X66:Open the input and output files\X${}\mathrel+\E{}$\6
\&{if} ${}((\\{argc}\E\T{0})\V\R(\\{strcmp}(\\{argv}[\T{0}],\39\.{"-"}))){}$\1\5
${}\\{output\_file}\K\\{stdout}{}$;\2\6
\&{else}  $\{$ \&{if} ${}((\\{output\_file}\K\\{fopen}(\\{argv}[\T{0}],\39%
\.{"w"}))\E\NULL)$ \X74:Handle error while opening output file\X $\}{}$\par
\fi

\M68. We have to set the flag that tells us that the input is coming from
\\{stdin}. In addition, if the mode is \.{COMPUTING}, we must open a
temporary file. Finally, we have to make the \\{input\_file} pointer
equal to \\{stdin}.
\Y\B\4\X68:Input file is stdin\X${}\E{}$\6
${}\\{input\_from\_pipe}\K\T{1}{}$;\6
\&{if} ${}(\\{mode}\E\.{COMPUTING})$ $\{$ \&{if} ${}((\\{temp\_file}\K%
\\{tmpfile}(\,))\E\NULL)$ $\{\X73:Error message about opening temporary file\X%
\}$ $\}$  \6
${}\\{input\_file}\K\\{stdin}{}$;\par
\U66.\fi

\M69.
\Y\B\4\X69:Close all files\X${}\E{}$\6
\\{fclose}(\\{input\_file});\6
\&{if} ${}(\\{mode}\E\.{COMPUTING}){}$\1\5
\\{fclose}(\\{output\_file});\2\par
\U6.\fi

\N70.  Error Messages.

This section contains the various error messages we send when things
go wrong.


\fi

\M71.
\Y\B\4\X71:Complain about improper command format\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{usage\_error};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ Command\ line\ ha}\)\.{s\ incorrect\
format.\\}\)\.{n"},\39\\{prog\_name});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%\%\ \ checksum\ \ input}\)\.{file\
outputfile\\n"});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\ \ \ \ \ is\ the\ format\ }\)\.{for\
installing\ a\ che}\)\.{cksum\ in\ a\ file.\\n"});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%\%\ checksum\ -v\ inpu}\)\.{tfile\\n"});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\ is\ the\ format\ for\ }\)\.{verifying\ an\
install}\)\.{ed\ checksum.\\n"});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par
\U8.\fi

\M72.
\Y\B\4\X72:Handle error while opening input file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{cannot\_open\_read\_file};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ cannot\ open\ inp}\)\.{ut\ file\ \%s%
\\n"},\39\\{prog\_name},\39{*}\\{argv});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par
\U66.\fi

\M73.
\Y\B\4\X73:Error message about opening temporary file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{cannot\_open\_temporary\_file};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ cannot\ open\ tem}\)\.{porary\ file.%
\\n"},\39\\{prog\_name});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par
\U68.\fi

\M74.
\Y\B\4\X74:Handle error while opening output file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{cannot\_open\_write\_file};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ cannot\ open\ out}\)\.{put\ file\ \%s%
\\n"},\39\\{prog\_name},\39{*}\\{argv});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par
\U67.\fi

\M75.
\Y\B\4\X75:Signal error while reading input file and abort\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{error\_reading\_input\_file};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ Error\ encounter}\)\.{ed\ while\ reading%
\ inp}\)\.{ut\ file.\\n"},\39\\{prog\_name});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par
\Us13\ET31.\fi

\M76.
\Y\B\4\X76:Issue complaint about the bad format of the input file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{status}\mathrel{+{\K}}\\{usage\_error};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"The\ input\ file\ did\ }\)\.{not\ have\ the\
correct}\)\.{\ format.\\n"});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"It\ should\ contain\ a}\)\.{\ line\ which\ has%
\ the\ }\)\.{word\ \\"checksum\\"\\n"});{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"and\ no\ other\ alphab}\)\.{etic\ characters.%
\\n"});{}$\6
\\{exit}(\.{EXIT\_FAILURE});\6
\4${}\}{}$\2\par

\U36.\fi


\inx
\I\.{\_\_GNUC\_\_}, 4.
\I\.{\_\_STDC\_\_}, 4.
\I\.{\_\_TURBOC\_\_}, 4.
\I\\{add\_a\_byte\_to\_checksum}, 4, 28, 29, 30, 48, 56, \[57].
\I\\{answer\_from\_critical}, \[12], 20, 35, 36.
\I\\{argc}, \[4], \[6], 8, 66, 67.
\I\.{ARGS}, \[4].
\I\\{argv}, \[4], \[6], 8, 66, 67, 72, 74.
\I\\{auxchksum}, \[12], 30, 48, 59.
\I\\{auxchksum2}, \[12], 30, 48, 59.
\I\|{c}, \[27].
\I\\{cannot\_open\_read\_file}, \[5], 72.
\I\\{cannot\_open\_temporary\_file}, \[5], 73.
\I\\{cannot\_open\_write\_file}, \[5], 74.
\I\\{cc}, 9, \[12], 26, 47, 51.
\I\\{cc\_guess}, \[46], 47.
\I\\{ccommand}, 6.
\I\\{char\_field\_length}, \[46], 47.
\I{Checksum size dependencies}, 11.
\I\\{chksm}, \[16], 17.
\I\\{chksum}, \[12], 29, 48, 51.
\I\.{COMPUTING}, 6, \[7], 10, 21, 25, 26, 32, 34, 65, 68, 69.
\I\\{crc\_table}, 55, \[56], 57, 62.
\I\\{critical}, 4, 14, \[15], 20.
\I\\{critical\_line}, 10, \[12], 21, 35, 38, 39, 40, 42, 43, 45, 47, 48, 49, 51.
\I\\{current\_line}, \[12], 13, 20, 21, 23, 25, 26, 29, 30, 31, 35.
\I\\{current\_line\_is\_critical}, \[12], 13, 20, 25, 26, 28.
\I\\{defined}, 4.
\I\\{dummy\_field\_pattern}, \[44], 45.
\I\.{EOF}, 13.
\I\\{error\_reading\_input\_file}, \[5], 75.
\I\\{exit}, 6, 51, 71, 72, 73, 74, 75, 76.
\I\.{EXIT\_FAILURE}, \[4], 6, 51, 71, 72, 73, 74, 75, 76.
\I\.{EXIT\_SUCCESS}, \[4], 6.
\I\\{fclose}, 31, 69.
\I\\{feof}, 13, 31.
\I\\{fgets}, 13, 31.
\I\\{file}, 2.
\I\\{fopen}, 66, 67.
\I\\{format}, \[50], 51.
\I\\{found\_critical\_line}, \[12], 13, 20, 25, 28, 51.
\I\\{fprintf}, 71, 72, 73, 74, 75, 76.
\I\\{fputs}, 25, 31, 49.
\I\\{fseek}, 31.
\I\\{ftell}, 24.
\I\|{i}, \[16], \[22], \[27], \[60].
\I\\{in\_word}, \[27].
\I\\{input\_file}, 13, 24, 31, \[65], 66, 68, 69.
\I\\{input\_from\_pipe}, 21, 25, 31, \[65], 68.
\I\\{isalpha}, 17.
\I\|{j}, \[16], \[60].
\I\\{jj}, \[16], 17, 18.
\I\|{k}, \[16].
\I\\{lc}, 9, \[12], 26, 43, 51.
\I\\{loc\_chksum}, \[14], 17, 38.
\I\\{loc\_critical\_line}, \[12], 24, 31.
\I\\{loc\_first\_quote\_mark}, \[14], 18, 23, 38, 39, 40, 48, 51.
\I\\{loc\_in\_line}, \[44], 45.
\I\\{loc\_second\_quote\_mark}, \[14], 19, 40.
\I\\{main}, 4, 5, \[6].
\I\\{merge\_three\_checksums}, 4, 48, \[63].
\I\\{mode}, 6, \[7], 8, 21, 25, 26, 28, 32, 65, 68, 69.
\I\.{MSDOS}, 4.
\I\\{MultiplyTwoPolys}, 4, \[60], 63.
\I\\{new\_byte}, \[4], 55, \[57].
\I\.{OK}, \[5].
\I\\{old\_char\_field\_length}, \[46], 47.
\I\\{old\_checksum}, 55.
\I\\{oldCheckSum}, \[4], \[57].
\I\\{one\_space}, \[41], 43, 45.
\I\\{output\_file}, 25, 31, 49, \[65], 67, 69.
\I\\{plist}, 4.
\I\\{position\_in\_line}, \[50], 51.
\I\\{printf}, 51.
\I\\{prog\_name}, \[5], 6, 71, 72, 73, 74, 75.
\I\\{quote}, \[41], 47.
\I\\{quote\_pattern}, \[37], 38.
\I\|{r}, \[60].
\I\\{rewind}, 31.
\I\|{s}, \[4], \[15], \[27], \[60], \[63].
\I\.{SEEK\_SET}, \[4], 31.
\I\.{SIZE}, \[11], 60.
\I\\{sprintf}, 43, 45, 47, 48.
\I\\{sscanf}, 51.
\I\\{status}, \[5], 6, 71, 72, 73, 74, 75, 76.
\I\\{stderr}, 71, 72, 73, 74, 75, 76.
\I\\{stdin}, 2, 21, 25, 31, 66, 68.
\I\\{stdout}, 1, 2, 9, 50, 66, 67.
\I\\{stored\_cc}, \[50], 51.
\I\\{stored\_chksum}, \[50], 51.
\I\\{stored\_lc}, \[50], 51.
\I\\{stored\_wc}, \[50], 51.
\I\\{strcat}, 38, 42, 43, 45, 47.
\I\\{strcmp}, 8, 66, 67.
\I\\{strcpy}, 21, 38, 39, 40.
\I\\{strlen}, 26, 45, 47.
\I\\{strncpy}, 48.
\I\|{t}, \[4], \[63].
\I\\{temp\_buf}, \[34], 35, 37, 38, 39, 40, 44, 45, 46, 47.
\I\\{temp\_buf2}, \[34], 43, 45, 47, 48.
\I\\{temp\_file}, 25, 31, \[65], 68.
\I\.{THINK\_C}, 4, 6.
\I\\{tmpfile}, 68.
\I\|{u}, \[4], \[57], \[60], \[63].
\I\\{u\_array}, \[60].
\I\\{usage\_error}, \[5], 71, 76.
\I\|{v}, \[4], \[60].
\I\\{v\_array}, \[60].
\I\.{VERIFY}, \[7], 8, 9, 21, 26, 28.
\I\\{verify\_successful}, 6, \[50], 51.
\I\\{vms}, 50.
\I\|{w}, \[63].
\I\\{w\_array}, \[60], 61.
\I\\{wc}, 9, \[12], 26, 44, 45, 51.
\I\\{word\_cnt}, \[27].
\I\\{word\_count}, 4, 26, \[27], 45.
\I\\{Zstring}, \[41], 42.
\fin
\I\X23:Adjust current line\X
\U21.
\I\X15, 27, 57, 60, 61, 62, 63:All functions\X
\U3.
\I\X20:Check if current line is critical line and set flags appropriately\X
\U13.
\I\X69:Close all files\X
\U6.
\I\X17, 18, 19:Code for ``critical''\X
\U15.
\I\X71:Complain about improper command format\X
\U8.
\I\X48:Compute the correct checksum and install it\X
\U33.
\I\X47:Compute the final character count and install it\X
\U33.
\I\X43:Compute the final line count and install it.\X
\U33.
\I\X45:Compute the final word count and install it\X
\U33.
\I\X32:Do endgame procedures\X
\U6.
\I\X31:Do second pass on input file\X
\U6.
\I\X33:Do \.{COMPUTING} endgame procedures\X
\U32.
\I\X51:Do \.{VERIFY} endgame procedures\X
\U32.
\I\X73:Error message about opening temporary file\X
\U68.
\I\X11:Global type definitions\X
\U3.
\I\X5, 14, 56:Global variables\X
\U3.
\I\X4:Global \#\&{include}s\X
\U3.
\I\X72:Handle error while opening input file\X
\U66.
\I\X74:Handle error while opening output file\X
\U67.
\I\X68:Input file is stdin\X
\U66.
\I\X42:Install the dummy checksum into the critical line.\X
\U33.
\I\X76:Issue complaint about the bad format of the input file\X
\U36.
\I\X6:Main\X
\U3.
\I\X66, 67:Open the input and output files\X
\U6.
\I\X8:Parse the command\X
\U6.
\I\X21:Process critical line\X
\U13.
\I\X13:Process the input file\X
\U6.
\I\X75:Signal error while reading input file and abort\X
\Us13\ET31.
\I\X35, 36, 38, 39, 40:Split \\{critical\_line} into two strings\X
\U33.
\I\X24:Store current location in input file\X
\U21.
\I\X28:Update checksums\X
\U13.
\I\X26:Update counts\X
\U13.
\I\X29:Update one checksum\X
\U28.
\I\X30:Update two checksums\X
\U28.
\I\X16:Variables for ``critical''\X
\U15.
\I\X7, 12, 22, 34, 37, 41, 44, 46, 50, 65:Variables local to \\{main}\X
\U6.
\I\X25:Write line to output file if appropriate\X
\U13.
\I\X49:Write the critical line to the output file\X
\U33.
\con
