summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/cweb-latex/examples/wcltx.w
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/latex/cweb-latex/examples/wcltx.w')
-rw-r--r--Master/texmf-dist/doc/latex/cweb-latex/examples/wcltx.w327
1 files changed, 327 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/cweb-latex/examples/wcltx.w b/Master/texmf-dist/doc/latex/cweb-latex/examples/wcltx.w
new file mode 100644
index 00000000000..4b82bd04f65
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/cweb-latex/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
+@<Header files to include@>@/
+@<Global variables@>@/
+@<Functions@>@/
+@<The main program@>
+
+@ We must include the standard I/O definitions, since we want to send
+formatted output to |stdout| and |stderr|.
+
+@<Header files...@>=
+#include <stdio.h>
+
+@ 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 */
+
+@<Global variables@>=
+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.
+
+@<The main...@>=
+main (argc,argv)
+ int argc; /* the number of arguments on the \UNIX/ command line */
+ char **argv; /* the arguments themselves, an array of strings */
+{
+ @<Variables local to |main|@>@;
+ prog_name=argv[0];
+ @<Set up option selection@>;
+ @<Process all the files@>;
+ @<Print the grand totals if there were multiple files @>;
+ 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.
+
+@<Var...@>=
+int file_count; /* how many files there are */
+char *which; /* which counts to print */
+
+@ @<Set up o...@>=
+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.
+
+@<Process...@>=
+argc--;
+do@+{
+ @<If a file is given, try to open |*(++argv)|; |continue| if unsuccessful@>;
+ @<Initialize pointers and counters@>;
+ @<Scan file@>;
+ @<Write statistics for file@>;
+ @<Close file@>;
+ @<Update grand totals@>; /* 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.
+
+@<Variabl...@>=
+int fd=0; /* file descriptor, initialized to |stdin| */
+
+@ @d READ_ONLY 0 /* read access code for system |open| routine */
+
+@<If a file...@>=
+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 file@>=
+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 */
+
+@<Var...@>=
+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 */
+
+@ @<Init...@>=
+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...
+
+@<Global var...@>=
+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.
+
+@<Scan...@>=
+while (1) {
+ @<Fill |buffer| if it is empty; |break| at end of file@>;
+ 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.
+
+@<Fill |buff...@>=
+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|.
+
+@<Write...@>=
+wc_print(which, char_count, word_count, line_count);
+if (file_count) printf (" %s\n", *argv); /* not |stdin| */
+else printf ("\n"); /* |stdin| */
+
+@ @<Upda...@>=
+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.
+
+@<Print the...@>=
+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)
+
+@<Fun...@>=
+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
+%