From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/cweb/examples/Makefile | 29 ++ .../latex/contrib/cweb/examples/compare/wcltx.aux | 26 ++ .../latex/contrib/cweb/examples/compare/wcltx.bbl | 8 + .../latex/contrib/cweb/examples/compare/wcltx.dvi | Bin 0 -> 24308 bytes .../latex/contrib/cweb/examples/compare/wcltx.idx | 40 ++ .../latex/contrib/cweb/examples/compare/wcltx.log | 114 ++++++ .../latex/contrib/cweb/examples/compare/wcltx.scn | 32 ++ .../latex/contrib/cweb/examples/compare/wcltx.tex | 412 +++++++++++++++++++++ macros/latex/contrib/cweb/examples/rcs.sty | 227 ++++++++++++ macros/latex/contrib/cweb/examples/tex-it | 203 ++++++++++ macros/latex/contrib/cweb/examples/wcltx.bib | 23 ++ macros/latex/contrib/cweb/examples/wcltx.w | 327 ++++++++++++++++ 12 files changed, 1441 insertions(+) create mode 100644 macros/latex/contrib/cweb/examples/Makefile create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.aux create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.bbl create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.dvi create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.idx create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.log create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.scn create mode 100644 macros/latex/contrib/cweb/examples/compare/wcltx.tex create mode 100644 macros/latex/contrib/cweb/examples/rcs.sty create mode 100644 macros/latex/contrib/cweb/examples/tex-it create mode 100644 macros/latex/contrib/cweb/examples/wcltx.bib create mode 100644 macros/latex/contrib/cweb/examples/wcltx.w (limited to 'macros/latex/contrib/cweb/examples') diff --git a/macros/latex/contrib/cweb/examples/Makefile b/macros/latex/contrib/cweb/examples/Makefile new file mode 100644 index 0000000000..e23e3056db --- /dev/null +++ b/macros/latex/contrib/cweb/examples/Makefile @@ -0,0 +1,29 @@ +# $Id: Makefile,v 1.5 1995/11/21 00:42:38 schrod Exp $ +#---------------------------------------------------------------------- + + +all:: wcltx.dvi + + +wcltx.dvi: wcltx.tex wcltx.bib ../cweb.cls + tex-it latex wcltx + rm -f wcltx.blg + +wcltx.tex: wcltx.w + cweave wcltx + + + AUX = *.aux *.bbl *.dvi *.idx *.log *.scn *.tex + +distrib:: + decomment-tex /usr/local/lib/texmf/tex/latex/misc/rcs.sty \ + 'from CTAN, directory macros/tex/latex/contrib/supported/rcs/.' \ + >rcs.sty + cp /usr/local/bin/tex-it . + $(MAKE) all + mkdir compare + mv $(AUX) compare + + +clean:: + /bin/rm -f $(AUX) diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.aux b/macros/latex/contrib/cweb/examples/compare/wcltx.aux new file mode 100644 index 0000000000..c602ac2179 --- /dev/null +++ b/macros/latex/contrib/cweb/examples/compare/wcltx.aux @@ -0,0 +1,26 @@ +\relax +\citation{litprog:schrod:cweb} +\@writefile{toc}{\contentsline {section}{\numberline {1}An example of {\tt CWEB\/}{}}{1}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{1}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{1}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{2}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{2}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{2}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{3}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{3}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{3}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{3}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{4}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{4}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{4}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{4}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{4}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{5}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{5}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{5}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{5}} +\bibstyle{plain} +\bibdata{wcltx} +\bibcite{litprog:schrod:cweb}{1} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{6}} +\@writefile{toc}{\contentsline {chunk}{\copy \cweb@chunk_marker }{6}} diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.bbl b/macros/latex/contrib/cweb/examples/compare/wcltx.bbl new file mode 100644 index 0000000000..1e95c84cce --- /dev/null +++ b/macros/latex/contrib/cweb/examples/compare/wcltx.bbl @@ -0,0 +1,8 @@ +\begin{thebibliography}{1} + +\bibitem{litprog:schrod:cweb} +Klaus Guntermann and Joachim Schrod. +\newblock {\WEB} adapted to {C}. +\newblock {\em TUGboat}, 7(3):134--137, 1986. + +\end{thebibliography} diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.dvi b/macros/latex/contrib/cweb/examples/compare/wcltx.dvi new file mode 100644 index 0000000000..468bc34d4b Binary files /dev/null and b/macros/latex/contrib/cweb/examples/compare/wcltx.dvi differ diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.idx b/macros/latex/contrib/cweb/examples/compare/wcltx.idx new file mode 100644 index 0000000000..dc79615c80 --- /dev/null +++ b/macros/latex/contrib/cweb/examples/compare/wcltx.idx @@ -0,0 +1,40 @@ +\I\\{argc}, \[5], 7, 8. +\I\\{argv}, \[5], 7, 10, 17. +\I\\{buf\_end}, \[12], 13, 16. +\I\\{buf\_size}, \[12], 16. +\I\\{buffer}, \[12], 13, 16. +\I\.{BUFSIZ}, 12. +\I\|{c}, \[12]. +\I\.{cannot open file}, 10. +\I\\{cannot\_open\_file}, \[4], 10. +\I\\{char\_count}, \[12], 13, 16, 17, 18, \[20]. +\I\\{close}, 11. +\I\\{exit}, 5. +\I\\{fd}, \[9], 10, 11, 16. +\I\\{file\_count}, \[6], 7, 10, 17, 19. +\I\\{fprintf}, 10, 20. +\I\\{in\_word}, \[12], 13, 15. +\I{Joke}, 14. +\I\\{line\_count}, \[12], 13, 15, 17, 18, \[20]. +\I\\{main}, \[5], 14. +\I\.{OK}, \[4]. +\I\\{open}, 10. +\I\\{print\_count}, \[20]. +\I\\{printf}, 17, 19, 20. +\I\\{prog\_name}, \[4], 5, 10, 20. +\I\\{ptr}, \[12], 13, 15, 16. +\I\\{read}, 16. +\I\.{READ\_ONLY}, \[10]. +\I\\{status}, \[4], 5, 10, 20. +\I\\{stderr}, 3, 10, 20. +\I\\{stdin}, 9, 17. +\I\\{stdout}, 3. +\I\\{tot\_char\_count}, \[14], 18, 19. +\I\\{tot\_line\_count}, \[14], 18, 19. +\I\\{tot\_word\_count}, \[14], 18, 19. +\I\.{Usage: ...}, 20. +\I\\{usage\_error}, \[4], 20. +\I\\{wc\_print}, 17, 19, \[20]. +\I\\{which}, \[6], 7, 17, 19, \[20]. +\I\\{word\_count}, \[12], 13, 15, 17, 18, \[20]. + diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.log b/macros/latex/contrib/cweb/examples/compare/wcltx.log new file mode 100644 index 0000000000..a3f0d6136f --- /dev/null +++ b/macros/latex/contrib/cweb/examples/compare/wcltx.log @@ -0,0 +1,114 @@ +This is TeX, Version 3.1415 (C version 6.1) (format=latex 95.7.29) 30 NOV 1995 16:52 +**wcltx +(wcltx.tex +LaTeX2e <1995/06/01> patch level 3 +Hyphenation patterns for english, german, loaded. +(/usr/local/lib/texmf/tex/generic/misc/cwebmac.tex) (../cweb.cls +Document Class: cweb 1995/11/30 v3.6 LaTeX markup for CWEB sources +(../keyvald.sty +Package: keyvald 1994/08/23 v1.08.1 key=value parser (DPC) w/ defaults (js) +) (/usr/local/lib/texmf/tex/latex/base/article.cls +Document Class: article 1995/06/26 v1.3g Standard LaTeX document class +(/usr/local/lib/texmf/tex/latex/base/size10.clo +File: size10.clo 1995/06/19 v1.3e Standard LaTeX file (size option) +) +\c@part=\count82 +\c@section=\count83 +\c@subsection=\count84 +\c@subsubsection=\count85 +\c@paragraph=\count86 +\c@subparagraph=\count87 +\c@figure=\count88 +\c@table=\count89 +\abovecaptionskip=\skip41 +\belowcaptionskip=\skip42 +\bibindent=\dimen102 +) (../cwebbase.tex +File: cwebbase.tex 1995/11/07 v1.4 CWEAVE tags for LaTeX markup +\cwbb@undefined=\toks15 +\cwbb@to_restore=\toks16 +\CwebChunkPreSkip=\skip43 +\cweb@chunk_marker=\box26 +LaTeX Font Info: Try loading font information for OMS+cmr on input line 598. + + +(/usr/local/lib/texmf/tex/latex/base/OMScmr.fd +File: OMScmr.fd 1995/04/22 v2.3f Standard LaTeX font definitions +) +LaTeX Font Info: Font shape `OMS/cmr/m/n' in size <10> not available +(Font) Font shape `OMS/cmsy/m/n' tried instead on input line 598. +\c@chunk=\count90 +\c@section2=\count91 +\c@section3=\count92 +\c@section4=\count93 +\c@section5=\count94 +\c@section6=\count95 +\c@section7=\count96 +\c@section8=\count97 +\c@section9=\count98 +\c@section10=\count99 +\CwebSectPreSkip=\skip44 +\CwebProgPenalty=\count100 +\cwbb@save@parskip=\skip45 +\cwbb@save@rightskip=\skip46 +\cwbb@save@sem_sfcode=\count101 +\cwbb@save@pretolerance=\count102 +\cwbb@save@hyphenpenalty=\count103 +\cwbb@save@exhyphenpenalty=\count104 +\CwebIndentUnit=\dimen103 +\cwbb@indent=\dimen104 +\cwbb@bak=\box27 +\cwbb@bakk=\box28 +\cwbb@pointer=\box29 +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line 1454. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line 1454. +\cwbb@decr=\box30 +\cwbb@incr=\box31 +) +\CwebTocIndent=\dimen105 +\CwebTocIndentMaxLevel=\count105 +\cwebIndexIntro=\toks17 +) (rcs.sty +Package: rcs 1995/08/02 v2.9 typeset info from RCS fields +\rcsLogIntro=\toks18 +) (wcltx.aux) +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 39. +LaTeX Font Info: ... okay on input line 39. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <8> on input line 47. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <6> on input line 47. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <12> on input line 51. + *1 +[1 + +] [2] [3] [4] [5] (wcltx.bbl [6]) [7] Index: (wcltx.idx) [8 + + +] +List of Refinements: (wcltx.scn) [9 + +] (wcltx.aux) ) +Here is how much of TeX's memory you used: + 709 strings out of 10921 + 7728 string characters out of 72294 + 56323 words of memory out of 262141 + 3583 multiletter control sequences out of 9500 + 8738 words of font info for 32 fonts, out of 100000 for 255 + 14 hyphenation exceptions out of 607 + 29i,8n,22p,172b,316s stack positions out of 300i,40n,60p,3000b,4000s + +Output written on wcltx.dvi (9 pages, 24308 bytes). diff --git a/macros/latex/contrib/cweb/examples/compare/wcltx.scn b/macros/latex/contrib/cweb/examples/compare/wcltx.scn new file mode 100644 index 0000000000..4b0fbe3d4a --- /dev/null +++ b/macros/latex/contrib/cweb/examples/compare/wcltx.scn @@ -0,0 +1,32 @@ +\I\X11:Close file\X +\U8. +\I\X16:Fill \PB{\\{buffer}} if it is empty; \PB{\&{break}} at end of file\X +\U15. +\I\X20:Functions\X +\U2. +\I\X4, 14:Global variables\X +\U2. +\I\X3:Header files to include\X +\U2. +\I\X10:If a file is given, try to open \PB{${*}(\PP\\{argv})$}; \PB{% +\&{continue}} if unsuccessful\X +\U8. +\I\X13:Initialize pointers and counters\X +\U8. +\I\X19:Print the grand totals if there were multiple files\X +\U5. +\I\X8:Process all the files\X +\U5. +\I\X15:Scan file\X +\U8. +\I\X7:Set up option selection\X +\U5. +\I\X5:The main program\X +\U2. +\I\X18:Update grand totals\X +\U8. +\I\X6, 9, 12:Variables local to \PB{\\{main}}\X +\U5. +\I\X17:Write statistics for file\X +\U8. + 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} \.{}\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 diff --git a/macros/latex/contrib/cweb/examples/rcs.sty b/macros/latex/contrib/cweb/examples/rcs.sty new file mode 100644 index 0000000000..e3cfaec72e --- /dev/null +++ b/macros/latex/contrib/cweb/examples/rcs.sty @@ -0,0 +1,227 @@ +% This is a stripped version of rcs.sty, +% all comment lines and empty lines were discarded to save space. YOU +% ARE NOT ALLOWED to use this file for your own work. You may ONLY +% redistribute it as part of the complete distribution you received it. +% This file was created at Thu Nov 30 15:51:58 UTC 1995. + +% The original file may be retrieved +% from CTAN, directory macros/tex/latex/contrib/supported/rcs/.. + +% ====================================================================== + +\ifx \rcs@loaded\undefined + \def\rcs@loaded{$StyleRevision: 2.9 $} +\else + \PackageWarningNoLine{rcs}% + {Some other package already uses namespace `rcs'} +\fi +\begingroup + \def\RCSPackage#1#2 $#3: #4 #5\endRCS $#6: #7 #8\endRCS{% + \def\date{#4}\def\id{v#7}% + \ProvidesPackage{#1}[\date\space\id\space #2]% + } + \RCSPackage{rcs}{typeset info from RCS fields} + $StyleDate: 1995/08/02 12:09:07 $: 9999/00/00 \endRCS + $StyleRevision: 2.9 $: 0.0 \endRCS +\endgroup +\ifx \CatEscape\undefined + \chardef\CatEscape=0 + \chardef\CatOpen=1 + \chardef\CatClose=2 + \chardef\CatIgnore=9 + \chardef\CatLetter=11 + \chardef\CatOther=12 + \chardef\CatActive=13 + \chardef\CatUsCode=\catcode`\_ +\fi +\catcode`\_=\CatLetter % top level macro file +\def\RcsEmptyValue{} +\def\rcs_split_field #1: #2 :#3\end_value{% + \def\RCS_keyword{#1}% + \def\RCS_value{#2}% + \ifx \RCS_value\empty + \let\RCS_value\RcsEmptyValue + \fi + } +\def\RCS $#1${% + \rcs_split_field #1: {} :\end_value + \expandafter\let \csname RCS\rcs_raw_if_handle\RCS_keyword\endcsname + \RCS_value + \csname RcsHandle\RCS_keyword\endcsname + } +\def\rcs_raw_if_handle{% + \@ifundefined{RcsHandle\RCS_keyword}{}{Raw}% + } +\def\RcsHandleDate{% + \ifx \today\undefined + \expandafter\let \csname RCS\RCS_keyword\endcsname \RCS_value + \else + \ifx \RCS_value\RcsEmptyValue + \@namedef{RCS\RCS_keyword}{\today}% + \let\RCSTime\empty + \else + \expandafter\rcs_set_date \RCS_value\end_date + \fi + \fi + } +\def\rcs_set_date #1/#2/#3 #4\end_date{% + \begingroup + \day #3 % <-- space! + \month #2 % <-- space! + \year #1 % <-- space! + \expandafter\xdef \csname RCS\RCS_keyword\endcsname {\today}% + \endgroup + \def\RCSTime{#4}% + } +\newtoks\rcsLogIntro + \rcsLogIntro={} +\def\rcsAuthor#1#2{\@namedef{rcs_author:#1}{#2}} +\def\RCS_get_author#1{% + \@ifundefined{rcs_author:#1}{#1}{\@nameuse{rcs_author:#1}}% + } +\def\RcsLogStyle{% + \def\RcsLogHeading{\subsubsection*}% + \footnotesize + } +\def\rcs_log_hdr#1,v\end_value{% + \@rcs_empty_log@false + \RcsLogHeading{\RcsLogHeadingName #1}% + \the\rcsLogIntro + } +\def\rcs_empty_log_value{% + \global\@rcs_empty_log@true % that's most probably in a group! + \RcsUnknownFile % text for unknown file name + ,v% % assert calling env + } +\newif\if@rcs_empty_log@ +\def\RcsLogHeadingName{Revision Log for \tt} % file name in monospace +\def\RcsUnknownFile{\rm $\langle\,$Unknown file name$\,\rangle$} +\def\RcsEmptyLog{{\itshape No log entries available.}} +\def\RcsLogRevision#1#2#3#4{% + \item [Revision #1]% + (created at \RcsLogDate #2\endDate\space \RcsLogTime{#3} % <-- space! + by \RCS_get_author{#4})\\\relax + } +\def\RcsLogDate #1/#2/#3\endDate{% + \begingroup + \day #3 % <-- space! + \month #2 % <-- space! + \year #1 % <-- space! + \today + \endgroup + } +\def\RcsLogTime#1{\ignorespaces} +\def\rcs_settime{% + \def\RcsLogTime##1{[##1]}% + } +\def\rcslog{% + \@ifnextchar[% % ] (Emacs) + \rcslog_configure + {\rcslog_configure[]}% + } +\def\rcslog_configure[#1]{% + \let\Revision\rcslog_revision + \let\settime\rcs_settime + \RcsLogStyle + #1% + \afterassignment\rcslog_skipcr + \let\next + } +\def\rcslog_skipcr{% + \ifx \next $% + \def\next{\rcslog_field $}% + \else\ifx \next\par + \let\next\rcslog_field + \else + \PackageError{rcs}{Missing RCS Log field in environment}{% +The RCS Log field must be the very first text in the rcslog\MessageBreak +environment. I will discard the rest of your input line and try to\MessageBreak +recover then. If you think this won't work, exit now.\MessageBreak +Otherwise press and cross your fingers!} + \let\next\rcslog_discard_line + \fi\fi + \next + } +\def\rcslog_discard_line{% + \begingroup + \obeylines + \rcslog_gobble_line + } +\begingroup +\obeylines +\gdef\rcslog_gobble_line #1^^M{% + \endgroup% + \afterassignment\rcslog_skipcr% + \let\next% + } +\endgroup +\def\rcslog_field{% + \begingroup + \obeylines + \rcslog_get_field + } +\begingroup +\obeylines +\gdef\rcslog_get_field #1^^M{% + \endgroup% + \rcslog_set_field{#1}% + } +\endgroup +\def\rcslog_set_field#1{% + \let\RcsEmptyValue\rcs_empty_log_value + \RCS #1% + \expandafter\rcs_log_hdr \RCS_value\end_value + \list{}\RcsLogListStyle % empty label, layout configurable + \if@rcs_empty_log@ + \item []\RcsEmptyLog % supply missing item + \fi + } +\def\RcsLogListStyle{% + \global\@listdepth\z@ + \labelwidth\z@ % item label w/o fixed size + \itemindent -\leftmargin % move label before start of line + \advance\itemindent \labelsep % label was moved too much + \def\makelabel##1{\bf ##1}% % how to typeset labels + \parsep\z@skip % no space between pars in items + \listparindent 1em % <-- space! indent pars in items + }% +\let\endrcslog\endtrivlist +\def\rcslog_revision{% + \begingroup + \obeylines + \rcslog_get_revinfo + } +\begingroup +\obeylines +\gdef\rcslog_get_revinfo #1 #2 #3 #4^^M{% + \endgroup% + \RcsLogRevision{#1}{#2}{#3}{#4}% + } +\endgroup +\def\RCSdate $#1${% + \RCS $#1$% + \expandafter\date \expandafter{\csname RCS\RCS_keyword\endcsname}% + } +\def\RCSID{% + \@ifnextchar\bgroup + \rcsid_get_field + \rcs_id + } +\def\rcsid_get_field#1{\rcs_id #1} +\def\rcs_id $#1${% + \RCS $#1$% + \begingroup + \let\protect\noexpand + \xdef\@oddfoot{% + \reset@font + \protect\framebox[\textwidth]{\RCS_keyword: \RCS_value}% + }% + \endgroup + \global\let\@evenfoot\@oddfoot + } +\def\RCSdef $#1${% + \typeout{RCS field: $#1$}% + \RCS $#1$% + } +\catcode`\_=\CatUsCode +\endinput diff --git a/macros/latex/contrib/cweb/examples/tex-it b/macros/latex/contrib/cweb/examples/tex-it new file mode 100644 index 0000000000..07a8e98ad3 --- /dev/null +++ b/macros/latex/contrib/cweb/examples/tex-it @@ -0,0 +1,203 @@ +#!/bin/sh +# $ITI: tex-it,v 1.3 1995/06/14 10:49:12 schrod Exp $ +#---------------------------------------------------------------------- + +# +# tex-it --- transform a TeX document to a final DVI file +# +# (history at end) + + +# SYNOPSIS +# +# tex-it [-bi] tex-cmd file +# +# tex-it runs 'tex-cmd' on 'file' as often as necessary to produce a +# DVI file where all cross references are resolved. That convergence +# is reached by analyzing auxilliary files: +# -- If file.toc has changed, the table of contents is not up to date. +# -- If file.idx has changed, the index is not up to date. +# MakeIndex is assumed to be used for creating the index. +# -- If file.aux has changed, cross references are not up to date. +# -- If file.aux contains a "\bibdata" tag and if the set of +# "\citation" tags have changed, then BibTeX is run. +# +# No other auxilliary files are handled. No subdocuments (via +# "\include") are supported. +# +# 'tex-cmd' may be more than one word. +# +# +# OPTIONS +# `-b' skip test for BibTeX +# `-i' skip test for MakeIndex + +# NOTE: On HP-UX this script is not functional, you have to substitute +# /bin/sh by /bin/ksh in the first line. (/bin/sh doesn't have the +# getopts builtin.) + + +cmd=`basename $0` +usage() +{ + echo "usage: $cmd [-bi] tex-cmd file" >&2 + exit 1 +} + + +# Normalize and check arguments. + +do_bibtex=true +do_makeindex=true +while getopts 'bi' option + do case "$option" in + b) do_bibtex='' + ;; + i) do_makeindex='' + ;; + *) usage + ;; + esac + done + +shift `expr $OPTIND - 1` +test $# -gt 0 || usage + + +# Get file name (last argument), discard extension if necessary. + +file=`eval "echo \\$$#"` +file=`echo $file | sed 's/\.[^.]*//'` + + +# Create temporary directory for auxilliary files to compare. Discard +# that directory if the script is terminated. Note that trap handler +# for 0 is executed at the end of the trap handler for the other +# signals. + +tmp=/tmp/tex$$ +trap "/bin/rm -rf $tmp" 0 +trap "exit 4" 1 2 3 15 +mkdir $tmp + + +# ------------------------------------------------------------ +# +# Set up functions that save auxilliary information and check if they +# have changed. Save functions are called `save_', check +# functions are called `check_'. Check functions set $run_tex to +# "true" if TeX must be run anew. Check functions may run programs to +# create other auxilliary files. + + +# aux: table of contents & cross references +# +# We don't check for *.toc files. LaTeX stores the information in the +# AUX file anyhow, and plain-based macros typically produce the table +# of contents at the end of the document, when it's guaranteed to be +# OK. + +save_aux() +{ + if [ -f "$file.aux" ] + then cp "$file.aux" $tmp + else touch "$tmp/$file.aux" + fi +} + +check_aux() +{ + test -f "$file.aux" || return 0 + cmp -s "$file.aux" "$tmp/$file.aux" || run_tex=true +} + + +# bibtex: Citations + +save_bibtex() +{ + if [ -f "$file.aux" ] + then egrep '^\\(citation|bibdata)' "$file.aux" | + sort >"$tmp/$file.bib" + else touch "$tmp/$file.bib" + fi +} + + +check_bibtex() +{ + test "$do_bibtex" -a -f "$file.aux" || return 0 + egrep '^\\(citation|bibdata)' "$file.aux" | sort >$tmp/bib.new + if grep '^\\bibdata' $tmp/bib.new >/dev/null + then if cmp -s "$tmp/$file.bib" $tmp/bib.new + then : do nothing + else bibtex "$file" + run_tex=true + fi + fi +} + + +# idx: raw index data + +save_idx() +{ + if [ -f "$file.idx" ] + then cp "$file.idx" $tmp + else touch "$tmp/$file.idx" + fi +} + +check_idx() +{ + test "$do_makeindex" -a -f "$file.idx" || return 0 + if cmp -s "$file.idx" "$tmp/$file.idx" + then : do nothing + else makeindex "$file" + run_tex=true + fi +} + + +# Two functions that collect the functions above. + +save_aux_info() +{ + save_aux + save_bibtex + save_idx +} + +check_aux_info() +{ + check_aux + check_bibtex + check_idx +} + + +# Process the document by TeX. Determine if TeX must be run anew by +# the functions realized above. + +run_tex=true +while [ "$run_tex" ] + do save_aux_info + "$@" + run_tex='' + check_aux_info + done + + + +#====================================================================== +# +# $ITIlog: tex-it,v $ +# Revision 1.3 1995/06/14 10:49:12 schrod +# HP-UX /bin/sh doesn't grok getopts, use ksh instead. +# +# Revision 1.2 1995/04/19 14:31:06 schrod +# Support MakeIndex call, too. +# +# Revision 1.1 1995/03/14 17:07:26 schrod +# Added script to process a TeX document. +# diff --git a/macros/latex/contrib/cweb/examples/wcltx.bib b/macros/latex/contrib/cweb/examples/wcltx.bib new file mode 100644 index 0000000000..007879df1f --- /dev/null +++ b/macros/latex/contrib/cweb/examples/wcltx.bib @@ -0,0 +1,23 @@ +$Id: wcltx.bib,v 1.1 1993/04/09 15:36:52 schrod Exp $ +---------------------------------------------------------------------- + +% +% extracted from litprog.bib database +% + +@string{ tub = "TUGboat"} + +@article{litprog:schrod:cweb, + author = {Klaus Guntermann and Joachim Schrod}, + title = {{\WEB} adapted to {C}}, + journal = tub, + volume = 7, + number = 3, + month = {}, + year = 1986, + pages = {134-137}, + annote = {\js{} My {\small CWEB}, an adaption of Knuth's Pascal +\WEB{}, ie, written in \WEB{}. Created to write an IBM~/370 +assembler/emulater for undergrad CS courses. I was an graduate +student, Klaus was my supervisor then.} +} diff --git a/macros/latex/contrib/cweb/examples/wcltx.w b/macros/latex/contrib/cweb/examples/wcltx.w new file mode 100644 index 0000000000..4b82bd04f6 --- /dev/null +++ b/macros/latex/contrib/cweb/examples/wcltx.w @@ -0,0 +1,327 @@ +% $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 + + + +@* 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.) + +@ 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}: + +@c +@
@/ +@@/ +@@/ +@ + +@ We must include the standard I/O definitions, since we want to send +formatted output to |stdout| and |stderr|. + +@
= +#include + +@ The |status| variable will tell 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. + +@d OK 0 /* |status| code for successful run */ +@d usage_error 1 /* |status| code for improper syntax */ +@d cannot_open_file 2 /* |status| code for file access error */ + +@= +int status=OK; /* exit status of command, initially |OK| */ +char *prog_name; /* who we are */ + +@ Now we come to the general layout of the |main| function. + +@= +main (argc,argv) + int argc; /* the number of arguments on the \UNIX/ command line */ + char **argv; /* the arguments themselves, an array of strings */ +{ + @@; + prog_name=argv[0]; + @; + @; + @; + exit(status); +} + +@ 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. + +@= +int file_count; /* how many files there are */ +char *which; /* which counts to print */ + +@ @= +which="lwc"; /* if no option is given, print all three values */ +if (argc>1 && *argv[1] == '-') { which=argv[1]+1; argc--; argv++; } +file_count=argc-1; + +@ 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 |do|~\dots~|while| loop because we should read from the +standard input if no file name is given. + +@= +argc--; +do@+{ + @; + @; + @; + @; + @; + @; /* even if there is only one file */ +}@+while (--argc>0); + +@ Here's the code to open the file. A special trick allows us to +handle input from |stdin| when no name is given. +Recall that the file descriptor to |stdin| is~0; that's what we +use as the default initial value. + +@= +int fd=0; /* file descriptor, initialized to |stdin| */ + +@ @d READ_ONLY 0 /* read access code for system |open| routine */ + +@= +if (file_count>0 && (fd=open(*(++argv),READ_ONLY))<0) { + fprintf (stderr, "%s: cannot open file %s\n", prog_name, *argv); +@.cannot open file@> + status|=cannot_open_file; + file_count--; + continue; +} + +@ @= +close(fd); + +@ We will do some homemade buffering in order to speed things up: Characters +will be read into the |buffer| array before we process them. +To do this we set up appropriate pointers and counters. + +@d buf_size BUFSIZ /* \texttt{stdio.h}'s |BUFSIZ| is chosen for efficiency */ + +@= +char buffer[buf_size]; /* we read the input into this array */ +register char *ptr; /* the first unprocessed character in |buffer| */ +register char *buf_end; /* the first unused position in |buffer| */ +register int c; /* current character, or number of characters just read */ +int in_word; /* are we within a word? */ +long word_count, line_count, char_count; /* number of words, lines, + and characters found in the file so far */ + +@ @= +ptr=buf_end=buffer; line_count=word_count=char_count=0; in_word=0; + +@ The grand totals must be initialized to zero at the beginning of the +program. If we made these variables local to |main|, we would have to +do this initialization explicitly; however, \CEE/'s globals are automatically +zeroed. (Or rather, ``statically zeroed.'') (Get it?) +@^Joke@> +%% -js: The joke would be better if the vars would be static, which +%% they aren't in the C sense... + +@= +long tot_word_count, tot_line_count, tot_char_count; + /* total number of words, lines, and chars */ + +@ 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. + +@= +while (1) { + @; + c=*ptr++; + if (c>' ' && c<0177) { /* visible ASCII codes */ + if (!in_word) {word_count++; in_word=1;} + continue; + } + if (c=='\n') line_count++; + else if (c!=' ' && c!='\t') continue; + in_word=0; /* |c| is newline, space, or tab */ +} + +@ Buffered I/O allows us to count the number of characters almost for free. + +@= +if (ptr>=buf_end) { + ptr=buffer; c=read(fd,ptr,buf_size); + if (c<=0) break; + char_count+=c; buf_end=buffer+c; +} + +@ It's convenient to output the statistics by defining a new function +|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 |stdin|. + +@= +wc_print(which, char_count, word_count, line_count); +if (file_count) printf (" %s\n", *argv); /* not |stdin| */ +else printf ("\n"); /* |stdin| */ + +@ @= +tot_line_count+=line_count; +tot_word_count+=word_count; +tot_char_count+=char_count; + +@ We might as well improve a bit on \UNIX/'s \wc{} by displaying the +number of files too. + +@= +if (file_count>1) { + wc_print(which, tot_char_count, tot_word_count, tot_line_count); + printf(" total in %d files\n",file_count); +} + +@ 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. + +@d print_count(n) printf("%8ld",n) + +@= +wc_print(which, char_count, word_count, line_count) +char *which; /* which counts to print */ +long char_count, word_count, line_count; /* given totals */ +{ + while (*which) + switch (*which++) { + case 'l': print_count(line_count); break; + case 'w': print_count(word_count); break; + case 'c': print_count(char_count); break; + default: if ((status & usage_error)==0) { + fprintf (stderr, "\nUsage: %s [-lwc] [filename ...]\n", prog_name); +@.Usage: ...@> + status|=usage_error; + } + } +} + +@ 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} + + +@ + +\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 +% -- cgit v1.2.3