summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/cweb/examples/compare/wcltx.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/cweb/examples/compare/wcltx.tex')
-rw-r--r--macros/latex/contrib/cweb/examples/compare/wcltx.tex412
1 files changed, 412 insertions, 0 deletions
diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.tex b/macros/latex/contrib/cweb/examples/compare/wcltx.tex
new file mode 100644
index 0000000000..58a91af024
--- /dev/null
+++ b/macros/latex/contrib/cweb/examples/compare/wcltx.tex
@@ -0,0 +1,412 @@
+\input cwebmac
+% $Id: wcltx.w,v 1.4 1995/08/29 17:27:57 schrod Exp $
+%------------------------------------------------------------
+
+%
+% wc: An example of CWEB by Silvio Levy and Donald E. Knuth
+%
+% [LaTeX]
+% (history at end)
+
+
+%% -js:
+%% should rework it: ANSI C compliance, POSIX.2 compliant option
+%% parsing with getopt(), including *all* required header files (ie,
+%% POSIX.1 compliance), using POSIX return codes and types, etc.
+
+
+
+\documentclass{cweb}
+
+\usepackage{rcs}
+
+
+%
+% some tags for this document
+%
+\def\CEE/{C\spacefactor 1000 }
+\def\cweb{{\tt CWEB\/}}
+\def\SPARC{SPARC\-\kern.1em station}
+\def\UNIX/{{\small UNIX\/}}
+\def\wc{{\tt wc\/}}
+\def\WEB{{\tt WEB\/}}
+
+\hfuzz=0.5pt
+
+
+
+
+\begin{document}
+
+
+
+\title{Counting words}
+\author{Silvio Levy\and Donald E. Knuth}
+\begingroup
+\def\thefootnote{\hbox{$^*$}}
+\footnotetext[0]{\LaTeX{} markup by Joachim Schrod.}
+\endgroup
+\RCSdate $Date: 1995/08/29 17:27:57 $
+
+\maketitle
+
+% not very interesting, only one starred section
+% \tableofcontents
+
+
+
+
+\N{1}{1}An example of \cweb{}. This example, based on a program by
+Klaus Guntermann and Joachim Schrod~\cite{litprog:schrod:cweb}
+presents the ``word count'' program from \UNIX/, rewritten in
+\cweb{} to demonstrate literate programming in \CEE/.%
+\footnote{%
+Incidentally, Klaus Guntermann and Joachim Schrod are now
+using this \cweb{} and have stopped the support for their version.
+Joachim Schrod contributed the \LaTeX{} style used for the markup of
+this document.
+}
+The level of detail in this document is intentionally high, for
+didactic purposes; many of the things spelled out here don't need to
+be explained in other programs.
+
+The purpose of \wc{} is to count lines, words, and/or characters in a
+list of files. The number of lines in a file is the number of newline
+characters it contains. The number of characters is the file length in bytes.
+A ``word'' is a maximal sequence of consecutive characters other than
+newline, space, or tab, containing at least one visible ASCII code.
+(We assume that the standard ASCII code is in use.)
+
+\fi
+
+\M{2}Most \cweb{} programs share a common structure. It's probably a
+good idea to state the overall structure explicitly at the outset,
+even though the various parts could all be introduced in unnamed
+sections of the code if we wanted to add them piecemeal.
+
+Here, then, is an overview of the file \texttt{wcltx.c} that is
+defined by this \cweb{} program \texttt{wcltx.w}:
+
+\Y\B\X3:Header files to include\X\6
+\X4:Global variables\X\6
+\X20:Functions\X\6
+\X5:The main program\X\par
+\fi
+
+\M{3}We must include the standard I/O definitions, since we want to send
+formatted output to \PB{\\{stdout}} and \PB{\\{stderr}}.
+
+\Y\B\4\X3:Header files to include\X${}\E{}$\6
+\8\#\&{include} \.{<stdio.h>}\par
+\U2.\fi
+
+\M{4} The \PB{\\{status}} variable will tell the operating system if the run
+was
+successful or not, and \PB{\\{prog\_name}} is used in case there's an error
+message to
+be printed.
+
+\Y\B\4\D$\.{OK}$ \5
+\T{0}\C{ \PB{\\{status}} code for successful run }\par
+\B\4\D$\\{usage\_error}$ \5
+\T{1}\C{ \PB{\\{status}} code for improper syntax }\par
+\B\4\D$\\{cannot\_open\_file}$ \5
+\T{2}\C{ \PB{\\{status}} code for file access error }\par
+\Y\B\4\X4:Global variables\X${}\E{}$\6
+\&{int} \\{status}${}\K\.{OK}{}$;\C{ exit status of command, initially \PB{%
+\.{OK}} }\6
+\&{char} ${}{*}\\{prog\_name}{}$;\C{ who we are }\par
+\A14.
+\U2.\fi
+
+\M{5}Now we come to the general layout of the \PB{\\{main}} function.
+
+\Y\B\4\X5:The main program\X${}\E{}$\6
+$\\{main}(\\{argc},\39\\{argv}){}$\1\1\6
+\&{int} \\{argc};\C{ the number of arguments on the \UNIX/ command line }\6
+\&{char} ${}{*}{*}\\{argv}{}$;\C{ the arguments themselves, an array of strings
+}\2\2\6
+${}\{{}$\1\6
+\X6:Variables local to \PB{\\{main}}\X\6
+${}\\{prog\_name}\K\\{argv}[\T{0}];{}$\6
+\X7:Set up option selection\X;\6
+\X8:Process all the files\X;\6
+\X19:Print the grand totals if there were multiple files\X;\6
+\\{exit}(\\{status});\6
+\4${}\}{}$\2\par
+\U2.\fi
+
+\M{6}If the first argument begins with a `\texttt{-}', the user is choosing
+the desired counts and specifying the order in which they should be
+displayed. Each selection is given by the initial character
+(lines, words, or characters). For example, `\texttt{-cl}' would cause
+just the number of characters and the number of lines to be printed,
+in that order.
+
+We do not process this string now; we simply remember where it is.
+It will be used to control the formatting at output time.
+
+\Y\B\4\X6:Variables local to \PB{\\{main}}\X${}\E{}$\6
+\&{int} \\{file\_count};\C{ how many files there are }\6
+\&{char} ${}{*}\\{which}{}$;\C{ which counts to print }\par
+\As9\ET12.
+\U5.\fi
+
+\M{7}\B\X7:Set up option selection\X${}\E{}$\6
+$\\{which}\K\.{"lwc"}{}$;\C{ if no option is given, print all three values }\6
+\&{if} ${}(\\{argc}>\T{1}\W{*}\\{argv}[\T{1}]\E\.{'-'}){}$\5
+${}\{{}$\1\6
+${}\\{which}\K\\{argv}[\T{1}]+\T{1};{}$\6
+${}\\{argc}\MM;{}$\6
+${}\\{argv}\PP;{}$\6
+\4${}\}{}$\2\6
+${}\\{file\_count}\K\\{argc}-\T{1}{}$;\par
+\U5.\fi
+
+\M{8}Now we scan the remaining arguments and try to open a file, if
+possible. The file is processed and its statistics are given.
+We use a \PB{\&{do}}~\dots~\PB{\&{while}} loop because we should read from the
+standard input if no file name is given.
+
+\Y\B\4\X8:Process all the files\X${}\E{}$\6
+$\\{argc}\MM;{}$\6
+\&{do}\5
+${}\{{}$\1\6
+\X10:If a file is given, try to open \PB{${*}(\PP\\{argv})$}; \PB{\&{continue}}
+if unsuccessful\X;\6
+\X13:Initialize pointers and counters\X;\6
+\X15:Scan file\X;\6
+\X17:Write statistics for file\X;\6
+\X11:Close file\X;\6
+\X18:Update grand totals\X;\C{ even if there is only one file }\6
+\4${}\}{}$\5
+\2\5
+\&{while} ${}(\MM\\{argc}>\T{0}){}$;\par
+\U5.\fi
+
+\M{9}Here's the code to open the file. A special trick allows us to
+handle input from \PB{\\{stdin}} when no name is given.
+Recall that the file descriptor to \PB{\\{stdin}} is~0; that's what we
+use as the default initial value.
+
+\Y\B\4\X6:Variables local to \PB{\\{main}}\X${}\mathrel+\E{}$\6
+\&{int} \\{fd}${}\K\T{0}{}$;\C{ file descriptor, initialized to \PB{\\{stdin}}
+}\par
+\fi
+
+\M{10}\B\D$\.{READ\_ONLY}$ \5
+\T{0}\C{ read access code for system \PB{\\{open}} routine }\par
+\Y\B\4\X10:If a file is given, try to open \PB{${*}(\PP\\{argv})$}; \PB{%
+\&{continue}} if unsuccessful\X${}\E{}$\6
+\&{if} ${}(\\{file\_count}>\T{0}\W(\\{fd}\K\\{open}({*}(\PP\\{argv}),\39\.{READ%
+\_ONLY}))<\T{0}){}$\5
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"\%s:\ cannot\ open\ fil}\)\.{e\ \%s\\n"},\39%
+\\{prog\_name},\39{*}\\{argv});{}$\6
+${}\\{status}\MRL{{\OR}{\K}}\\{cannot\_open\_file};{}$\6
+${}\\{file\_count}\MM;{}$\6
+\&{continue};\6
+\4${}\}{}$\2\par
+\U8.\fi
+
+\M{11}\B\X11:Close file\X${}\E{}$\6
+\\{close}(\\{fd});\par
+\U8.\fi
+
+\M{12}We will do some homemade buffering in order to speed things up:
+Characters
+will be read into the \PB{\\{buffer}} array before we process them.
+To do this we set up appropriate pointers and counters.
+
+\Y\B\4\D$\\{buf\_size}$ \5
+\.{BUFSIZ}\C{ \texttt{stdio.h}'s \PB{\.{BUFSIZ}} is chosen for efficiency }\par
+\Y\B\4\X6:Variables local to \PB{\\{main}}\X${}\mathrel+\E{}$\6
+\&{char} \\{buffer}[\\{buf\_size}];\C{ we read the input into this array }\6
+\&{register} \&{char} ${}{*}\\{ptr}{}$;\C{ the first unprocessed character in %
+\PB{\\{buffer}} }\6
+\&{register} \&{char} ${}{*}\\{buf\_end}{}$;\C{ the first unused position in %
+\PB{\\{buffer}} }\6
+\&{register} \&{int} \|c;\C{ current character, or number of characters just
+read }\6
+\&{int} \\{in\_word};\C{ are we within a word? }\6
+\&{long} \\{word\_count}${},{}$ \\{line\_count}${},{}$ \\{char\_count};\C{
+number of words, lines, and characters found in the file so far }\par
+\fi
+
+\M{13}\B\X13:Initialize pointers and counters\X${}\E{}$\6
+$\\{ptr}\K\\{buf\_end}\K\\{buffer};{}$\6
+${}\\{line\_count}\K\\{word\_count}\K\\{char\_count}\K\T{0};{}$\6
+${}\\{in\_word}\K\T{0}{}$;\par
+\U8.\fi
+
+\M{14}The grand totals must be initialized to zero at the beginning of the
+program. If we made these variables local to \PB{\\{main}}, we would have to
+do this initialization explicitly; however, \CEE/'s globals are automatically
+zeroed. (Or rather, ``statically zeroed.'') (Get it?)
+%% -js: The joke would be better if the vars would be static, which
+%% they aren't in the C sense...
+
+\Y\B\4\X4:Global variables\X${}\mathrel+\E{}$\6
+\&{long} \\{tot\_word\_count}${},{}$ \\{tot\_line\_count}${},{}$ \\{tot\_char%
+\_count};\C{ total number of words, lines, and chars }\par
+\fi
+
+\M{15}The present section, which does the counting that is \wc{}'s \emph{raison
+d'\^etre}, was actually one of the simplest to write. We look at each
+character and change state if it begins or ends a word.
+
+\Y\B\4\X15:Scan file\X${}\E{}$\6
+\&{while} (\T{1})\5
+${}\{{}$\1\6
+\X16:Fill \PB{\\{buffer}} if it is empty; \PB{\&{break}} at end of file\X;\6
+${}\|c\K{*}\\{ptr}\PP;{}$\6
+\&{if} ${}(\|c>\.{'\ '}\W\|c<\T{\~177}){}$\5
+${}\{{}$\C{ visible ASCII codes }\1\6
+\&{if} ${}(\R\\{in\_word}){}$\5
+${}\{{}$\1\6
+${}\\{word\_count}\PP;{}$\6
+${}\\{in\_word}\K\T{1};{}$\6
+\4${}\}{}$\2\6
+\&{continue};\6
+\4${}\}{}$\2\6
+\&{if} ${}(\|c\E\.{'\\n'}){}$\1\5
+${}\\{line\_count}\PP;{}$\2\6
+\&{else} \&{if} ${}(\|c\I\.{'\ '}\W\|c\I\.{'\\t'}){}$\1\5
+\&{continue};\2\6
+${}\\{in\_word}\K\T{0}{}$;\C{ \PB{\|c} is newline, space, or tab }\6
+\4${}\}{}$\2\par
+\U8.\fi
+
+\M{16}Buffered I/O allows us to count the number of characters almost for free.
+
+\Y\B\4\X16:Fill \PB{\\{buffer}} if it is empty; \PB{\&{break}} at end of file%
+\X${}\E{}$\6
+\&{if} ${}(\\{ptr}\G\\{buf\_end}){}$\5
+${}\{{}$\1\6
+${}\\{ptr}\K\\{buffer};{}$\6
+${}\|c\K\\{read}(\\{fd},\39\\{ptr},\39\\{buf\_size});{}$\6
+\&{if} ${}(\|c\Z\T{0}){}$\1\5
+\&{break};\2\6
+${}\\{char\_count}\MRL{+{\K}}\|c;{}$\6
+${}\\{buf\_end}\K\\{buffer}+\|c;{}$\6
+\4${}\}{}$\2\par
+\U15.\fi
+
+\M{17}It's convenient to output the statistics by defining a new function
+\PB{\\{wc\_print}}; then the same function can be used for the totals.
+Additionally we must decide here if we know the name of the file
+we have processed or if it was just \PB{\\{stdin}}.
+
+\Y\B\4\X17:Write statistics for file\X${}\E{}$\6
+$\\{wc\_print}(\\{which},\39\\{char\_count},\39\\{word\_count},\39\\{line%
+\_count});{}$\6
+\&{if} (\\{file\_count})\1\5
+${}\\{printf}(\.{"\ \%s\\n"},\39{*}\\{argv}){}$;\C{ not \PB{\\{stdin}} }\2\6
+\&{else}\1\5
+\\{printf}(\.{"\\n"});\C{ \PB{\\{stdin}} }\2\par
+\U8.\fi
+
+\M{18}\B\X18:Update grand totals\X${}\E{}$\6
+$\\{tot\_line\_count}\MRL{+{\K}}\\{line\_count};{}$\6
+${}\\{tot\_word\_count}\MRL{+{\K}}\\{word\_count};{}$\6
+${}\\{tot\_char\_count}\MRL{+{\K}}\\{char\_count}{}$;\par
+\U8.\fi
+
+\M{19}We might as well improve a bit on \UNIX/'s \wc{} by displaying the
+number of files too.
+
+\Y\B\4\X19:Print the grand totals if there were multiple files\X${}\E{}$\6
+\&{if} ${}(\\{file\_count}>\T{1}){}$\5
+${}\{{}$\1\6
+${}\\{wc\_print}(\\{which},\39\\{tot\_char\_count},\39\\{tot\_word\_count},\39%
+\\{tot\_line\_count});{}$\6
+${}\\{printf}(\.{"\ total\ in\ \%d\ files\\}\)\.{n"},\39\\{file\_count});{}$\6
+\4${}\}{}$\2\par
+\U5.\fi
+
+\M{20}Here now is the function that prints the values according to the
+specified options. The calling routine is supposed to supply a
+newline. If an invalid option character is found we inform
+the user about proper usage of the command. Counts are printed in
+8-digit fields so that they will line up in columns.
+
+\Y\B\4\D$\\{print\_count}(\|n)$ \5
+$\\{printf}(\.{"\%8ld"},\39\|n{}$)\par
+\Y\B\4\X20:Functions\X${}\E{}$\6
+$\\{wc\_print}(\\{which},\39\\{char\_count},\39\\{word\_count},\39\\{line%
+\_count}){}$\1\1\6
+\&{char} ${}{*}\\{which}{}$;\C{ which counts to print }\6
+\&{long} \\{char\_count}${},{}$ \\{word\_count}${},{}$ \\{line\_count};\C{
+given totals }\2\2\6
+${}\{{}$\1\6
+\&{while} ${}({*}\\{which}){}$\1\6
+\&{switch} ${}({*}\\{which}\PP){}$\5
+${}\{{}$\1\6
+\4\&{case} \.{'l'}:\5
+\\{print\_count}(\\{line\_count});\6
+\&{break};\6
+\4\&{case} \.{'w'}:\5
+\\{print\_count}(\\{word\_count});\6
+\&{break};\6
+\4\&{case} \.{'c'}:\5
+\\{print\_count}(\\{char\_count});\6
+\&{break};\6
+\4\&{default}:\6
+\&{if} ${}((\\{status}\AND\\{usage\_error})\E\T{0}){}$\5
+${}\{{}$\1\6
+${}\\{fprintf}(\\{stderr},\39\.{"\\nUsage:\ \%s\ [-lwc]\ }\)\.{[filename\ ...]%
+\\n"},\39\\{prog\_name});{}$\6
+${}\\{status}\MRL{{\OR}{\K}}\\{usage\_error};{}$\6
+\4${}\}{}$\2\6
+\4${}\}{}$\2\2\6
+\4${}\}{}$\2\par
+\U2.\fi
+
+\M{21}Incidentally, a test of this program against the system \wc{}
+command on a \SPARC\ showed that the ``official'' \wc{} was slightly
+slower. Furthermore, although that \wc{} gave an appropriate error
+message for the options `\texttt{-abc}', it made no complaints about the
+options `\texttt{-labc}'! Dare we suggest that the system routine
+might have been
+better if its programmer had used a more literate approach?
+
+
+
+\bibliographystyle{plain}
+\bibliography{wcltx}
+
+
+\fi
+
+\M{22}
+
+\cwebIndexIntro{%
+Here is a list of the identifiers used, and where they appear.
+Underlined entries indicate the place of definition. Error messages
+are also shown.
+}
+
+\end{document}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% $Log: wcltx.w,v $
+% Revision 1.4 1995/08/29 17:27:57 schrod
+% Recoded to LaTeX2e markup.
+%
+% Revision 1.3 1993/06/15 14:01:14 schrod
+% Renamed document to wcltx, must change \bibliography tag, too.
+%
+% Revision 1.2 1993/06/15 13:35:12 schrod
+% `cweb' is now a style, was an option formerly.
+%
+% Revision 1.1 1993/04/09 15:00:37 schrod
+% Initial revision
+%
+\fi
+
+
+\inx
+\fin
+\con