\input mcwebmac
% This file is part of mCWEB.
% This program by Markus Öllinger is based on
% CWEB 3.4 by Silvio Levy and Donald E. Knuth which in turn
% is based on a program by Knuth.
% It is distributed WITHOUT ANY WARRANTY, express or implied.
% Version 1.1 --- October 1998

% Copyright (C) 1996-1998 Markus Öllinger

% Permission is granted to make and distribute verbatim copies of this
% document provided that the copyright notice and this permission notice
% are preserved on all copies.

% Permission is granted to copy and distribute modified versions of this
% document under the conditions for verbatim copying, provided that the
% entire resulting derived work is given a different name and distributed
% under the terms of a permission notice identical to this one.

% Here is TeX material that gets inserted after \input mcwebmac
\def\hang{\hangindent 3em\indent\ignorespaces}
\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
\def\v{\char'174} % vertical (|) in typewriter font
\mathchardef\RA="3221 % right arrow
\mathchardef\BA="3224 % double arrow

\def\title{mCTANGLE (Version 1.1)}
\def\topofcontents{\null\vfill
  \centerline{\titlefont The {\ttitlefont mCTANGLE} processor}
  \vskip 15pt
  \centerline{(Version 1.1)}
  \vfill}
\def\botofcontents{\vfill\titlefalse}
\def\contentspagenumber{89}
%\def\title{APPENDIX E: CTANGLE}
%\let\K=\leftarrow
\pageno=\contentspagenumber \advance\pageno by 1
\let\maybe=\iftrue


\N{0}{1}Introduction.
This is the \.{mCTANGLE} program which is an extension to
\.{CWEB} by Silvio Levy and Donald E. Knuth,
based on \.{TANGLE} by Knuth.
I am thankful to Thomas \"Ollinger for his constructive criticism and %"
his help with the \TeX\ macros, and everbody who has contributed to
the original \.{CWEB}: Silvio Levy, D.~E.~Knuth,
Nelson Beebe, Hans-Hermann Bode (to whom the \CPLUSPLUS/ adaptation is due),
Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
Joachim Schrod, Lee Wittenberg, and others who have contributed improvements.

The ``banner line'' defined here should be changed whenever \.{mCTANGLE}
is modified.

\Y\B\4\D$\\{banner}$ \5
\.{"This\ is\ mCTANGLE\ (V}\)\.{ersion\ 1.1)\\n"}\par
\Y\B\X8:Include files\X\6
\ATH\6
\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X\6
\X18:Typedef declarations\X\6
\X19:Global variables\X\6
\X2:Predeclaration of procedures\X\par
\fi

\M{2}We predeclare several standard system functions here instead of including
their system header files, because the names of the header files are not as
standard as the names of the functions. (For example, some \CEE/ environments
have \.{<string.h>} where others have \.{<strings.h>}.)

\Y\B\4\X2:Predeclaration of procedures\X${}\E{}$\6
\&{extern} \&{int} \\{strlen}(\,);\C{ length of string }\6
\&{extern} \&{int} \\{strcmp}(\,);\C{ compare strings lexicographically }\6
\&{extern} \&{char} ${}{*}\\{strcpy}(\,){}$;\C{ copy one string to another }\6
\&{extern} \&{int} \\{strncmp}(\,);\C{ compare up to $n$ string characters }\6
\&{extern} \&{char} ${}{*}\\{strncpy}(\,){}$;\C{ copy up to $n$ string
characters }\6
\&{extern} \&{char} ${}{*}\\{strrchr}(\,){}$;\C{ find last occurrence of
character in string }\6
\&{extern} \&{char} ${}{*}\\{strchr}(\,){}$;\C{ find first occurrence of
character in string }\par
\As4, 34, 47, 53, 59, 64, 71, 116, 118, 128, 133, 137, 162, 165, 168, 171, 180,
193, 195, 197, 203, 213, 217, 221, 229, 234\ETs238.
\U1.\fi

\M{3}%modified
\.{CTANGLE} has a fairly straightforward outline.  It operates in
two phases: first it reads the source file, saving the \CEE/ code in
compressed form; then outputs the code, after shuffling it around.

Please read the documentation for \.{mcommon}, the set of routines common
to \.{CTANGLE} and \.{CWEAVE}, before proceeding further.

\Y\B\&{int} ${}\\{main}(\\{ac},\39\\{av}){}$\1\1\6
\&{int} \\{ac};\6
\&{char} ${}{*}{*}\\{av};\2\2{}$\6
${}\{{}$\1\6
${}\\{argc}\K\\{ac};{}$\6
${}\\{argv}\K\\{av};{}$\6
${}\\{program}\K\\{ctangle};{}$\6
${}\\{show\_banner}\K\\{show\_happiness}\K\\{show\_progress}\K\T{1};{}$\6
\\{scan\_args}(\,);\6
\&{if} (\\{show\_banner})\1\5
\\{printf}(\\{banner});\C{ print a ``banner line'' }\2\6
${}\\{argc}\K\\{ac};{}$\6
${}\\{argv}\K\\{av};{}$\6
\X206:Check for book file\X;\6
\&{return} \\{tangle\_file}(\,);\C{ run in old-style \.{CWEB} mode }\6
\4${}\}{}$\2\par
\fi

\M{4}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{int} \\{tangle\_file}(\,);\par
\fi

\M{5}%moved
Translates a \.{WEB} file. The argument vector \PB{\\{argv}} is scanned to find
out which file to tangle.
\Y\B\&{int} \\{tangle\_file}(\,)\1\1\2\2\6
${}\{{}$\1\6
\X20:Set initial values\X;\6
\\{common\_init}(\,);\6
\X26:Insert predefined identifiers into \PB{\\{name\_dir}}\X;\6
\X67:Create file name constant\X;\6
\\{phase\_one}(\,);\C{ read all the user's text and compress it into \PB{\\{tok%
\_mem}} }\6
\\{phase\_two}(\,);\C{ output the contents of the compressed tables }\6
\&{return} \\{wrap\_up}(\,);\C{ and exit gracefully }\6
\4${}\}{}$\2\par
\fi

\M{6}The following parameters were sufficient in the original \.{TANGLE} to
handle \TEX/,
so they should be sufficient for most applications of \.{CTANGLE}.
If you change \PB{\\{max\_bytes}}, \PB{\\{max\_names}} or \PB{\\{hash\_size}}
you should also
change them in the file \PB{\.{"mcommon.w"}}.

\Y\B\4\D$\\{max\_bytes}$ \5
\T{90000}\C{ the number of bytes in identifiers,   index entries, and section
names; used in \PB{\.{"mcommon.w"}} }\par
\B\4\D$\\{max\_toks}$ \5
\T{270000}\C{ number of bytes in compressed \CEE/ code }\par
\B\4\D$\\{max\_names}$ \5
\T{10000}\C{ number of identifiers, strings, section names;   must be less than
10240; used in \PB{\.{"mcommon.w"}} }\par
\B\4\D$\\{max\_texts}$ \5
\T{2500}\C{ number of replacement texts, must be less than 10240 }\par
\B\4\D$\\{hash\_size}$ \5
\T{353}\C{ should be prime; used in \PB{\.{"mcommon.w"}} }\par
\B\4\D$\\{longest\_name}$ \5
\T{1000}\C{ section names shouldn't be longer than this }\par
\B\4\D$\\{stack\_size}$ \5
\T{50}\C{ number of simultaneous levels of macro expansion }\par
\B\4\D$\\{buf\_size}$ \5
\T{256}\C{ for \.{CWEAVE} and \.{CTANGLE} }\par
\fi

\M{7}The next few sections contain stuff from \PB{\.{"mcommon.w"}} that must
be included in both \PB{\.{"mctangle.w"}} and \PB{\.{"mcweave.w"}}. It appears
in
file \PB{\.{"mcommon.h"}}, which needs to be updated when \PB{\.{"mcommon.w"}}
changes.

% This file is part of mCWEB.
% This program by Markus Öllinger is based on
% CWEB 3.4 by Silvio Levy and Donald E. Knuth which in turn
% is based on a program by Knuth.
% It is distributed WITHOUT ANY WARRANTY, express or implied.
% Version 1.1 --- October 1998

% Copyright (C) 1996-1998 Markus Öllinger

% Permission is granted to make and distribute verbatim copies of this
% document provided that the copyright notice and this permission notice
% are preserved on all copies.

% Permission is granted to copy and distribute modified versions of this
% document under the conditions for verbatim copying, provided that the
% entire resulting derived work is distributed under the terms of a
% permission notice identical to this one.

% Please send comments, suggestions, etc. to moell@ist.tu-graz.ac.at.

% The next few sections contain stuff from the file \PB{\.{"common.w"}} that
%has
% to be included in both \PB{\.{"ctangle.w"}} and \PB{\.{"cweave.w"}}. It
%appears in this
% file \PB{\.{"common.h"}}, which needs to be updated when \PB{\.{"common.w"}}
%changes.

First comes general stuff:

\Y\B\4\D$\\{ctangle}$ \5
\T{0}\par
\B\4\D$\\{cweave}$ \5
\T{1}\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\E{}$\6
\&{typedef} \&{short} \&{boolean};\6
\&{typedef} \&{char} \&{unsigned} \&{eight\_bits};\6
\&{extern} \&{boolean} \\{program};\C{ \.{CWEAVE} or \.{CTANGLE}? }\6
\&{extern} \&{int} \\{phase};\C{ which phase are we in? }\par
\As9, 10, 11, 12, 13, 14, 15, 16\ETs17.
\U1.\fi

\M{8}\B\X8:Include files\X${}\E{}$\6
\8\#\&{include} \.{<stdio.h>}\par
\As52, 69, 86\ETs224.
\U1.\fi

\M{9}Code related to the character set:

\Y\B\4\D$\\{and\_and}$ \5
\T{\~4}\C{ `\.{\&\&}'\,; corresponds to MIT's {\tentex\char'4} }\par
\B\4\D$\\{lt\_lt}$ \5
\T{\~20}\C{ `\.{<<}'\,;  corresponds to MIT's {\tentex\char'20} }\par
\B\4\D$\\{gt\_gt}$ \5
\T{\~21}\C{ `\.{>>}'\,;  corresponds to MIT's {\tentex\char'21} }\par
\B\4\D$\\{plus\_plus}$ \5
\T{\~13}\C{ `\.{++}'\,;  corresponds to MIT's {\tentex\char'13} }\par
\B\4\D$\\{minus\_minus}$ \5
\T{\~1}\C{ `\.{--}'\,;  corresponds to MIT's {\tentex\char'1} }\par
\B\4\D$\\{minus\_gt}$ \5
\T{\~31}\C{ `\.{->}'\,;  corresponds to MIT's {\tentex\char'31} }\par
\B\4\D$\\{not\_eq}$ \5
\T{\~32}\C{ `\.{!=}'\,;  corresponds to MIT's {\tentex\char'32} }\par
\B\4\D$\\{lt\_eq}$ \5
\T{\~34}\C{ `\.{<=}'\,;  corresponds to MIT's {\tentex\char'34} }\par
\B\4\D$\\{gt\_eq}$ \5
\T{\~35}\C{ `\.{>=}'\,;  corresponds to MIT's {\tentex\char'35} }\par
\B\4\D$\\{eq\_eq}$ \5
\T{\~36}\C{ `\.{==}'\,;  corresponds to MIT's {\tentex\char'36} }\par
\B\4\D$\\{or\_or}$ \5
\T{\~37}\C{ `\.{\v\v}'\,;  corresponds to MIT's {\tentex\char'37} }\par
\B\4\D$\\{dot\_dot\_dot}$ \5
\T{\~16}\C{ `\.{...}'\,;  corresponds to MIT's {\tentex\char'16} }\par
\B\4\D$\\{colon\_colon}$ \5
\T{\~6}\C{ `\.{::}'\,;  corresponds to MIT's {\tentex\char'6} }\par
\B\4\D$\\{period\_ast}$ \5
\T{\~26}\C{ `\.{.*}'\,;  corresponds to MIT's {\tentex\char'26} }\par
\B\4\D$\\{minus\_gt\_ast}$ \5
\T{\~27}\C{ `\.{->*}'\,;  corresponds to MIT's {\tentex\char'27} }\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{char} ${}\\{section\_text}[\\{longest\_name}+\T{1}]{}$;\C{ name being sought
for }\6
\&{char} ${}{*}\\{section\_text\_end}\K\\{section\_text}+\\{longest\_name}{}$;%
\C{ end of \PB{\\{section\_text}} }\6
\&{char} ${}{*}\\{id\_first}{}$;\C{ where the current identifier begins in the
buffer }\6
\&{char} ${}{*}\\{id\_loc}{}$;\C{ just after the current identifier in the
buffer }\par
\fi

\M{10}Code related to input routines:

\Y\B\4\D$\\{xisalpha}(\|c)$ \5
$(\\{isalpha}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\B\4\D$\\{xisdigit}(\|c)$ \5
$(\\{isdigit}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\B\4\D$\\{xisspace}(\|c)$ \5
$(\\{isspace}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\B\4\D$\\{xislower}(\|c)$ \5
$(\\{islower}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\B\4\D$\\{xisupper}(\|c)$ \5
$(\\{isupper}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\B\4\D$\\{xisxdigit}(\|c)$ \5
$(\\{isxdigit}(\|c)\W{}$((\&{eight\_bits}) \|c${}<\T{\~200}){}$)\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \&{char} \\{buffer}[\,];\C{ where each line of input goes }\6
\&{extern} \&{char} ${}{*}\\{buffer\_end}{}$;\C{ end of \PB{\\{buffer}} }\6
\&{extern} \&{char} ${}{*}\\{loc}{}$;\C{ points to the next character to be
read from the buffer}\6
\&{extern} \&{char} ${}{*}\\{limit}{}$;\C{ points to the last character in the
buffer }\par
\fi

\M{11}Code related to identifier and section name storage:
\Y\B\4\D$\\{length}(\|c)$ \5
$(\|c+\T{1})\MG\\{byte\_start}-(\|c)\MG{}$\\{byte\_start}\C{ the length of a
name }\par
\B\4\D$\\{print\_id}(\|c)$ \5
$\\{term\_write}((\|c)\MG\\{byte\_start},\39\\{length}((\|c)){}$)\C{ print
identifier }\par
\B\4\D$\\{llink}$ \5
\\{link}\C{ left link in binary search tree for section names }\par
\B\4\D$\\{rlink}$ \5
$\\{dummy}.{}$\\{Rlink}\C{ right link in binary search tree for section names }%
\par
\B\4\D$\\{root}$ \5
$\\{name\_dir}\MG{}$\\{rlink}\C{ the root of the binary search tree   for
section names }\par
\B\4\D$\\{chunk\_marker}$ \5
\T{0}\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} \&{name\_info} ${}\{{}$\1\6
\&{char} ${}{*}\\{byte\_start}{}$;\C{ beginning of the name in \PB{\\{byte%
\_mem}} }\6
\&{struct} \&{name\_info} ${}{*}\\{link};{}$\6
\&{union} ${}\{{}$\1\6
\&{struct} \&{name\_info} ${}{*}\\{Rlink}{}$;\C{ right link in binary search
tree for section       names }\6
\&{char} \\{Ilk};\C{ used by identifiers in \.{CWEAVE} only }\2\6
${}\}{}$ \\{dummy};\6
\&{char} ${}{*}\\{equiv\_or\_xref}{}$;\C{ info corresponding to names }\2\6
${}\}{}$ \&{name\_info};\C{ contains information about an identifier or section
name }\6
\&{typedef} \&{name\_info} ${}{*}\&{name\_pointer}{}$;\C{ pointer into array of
\&{name\_info}s }\6
\&{typedef} \&{name\_pointer} ${}{*}\&{hash\_pointer};{}$\6
\&{extern} \&{char} \\{byte\_mem}[\,];\C{ characters of names }\6
\&{extern} \&{char} ${}{*}\\{byte\_mem\_end}{}$;\C{ end of \PB{\\{byte\_mem}} }%
\6
\&{extern} \&{name\_info} \\{name\_dir}[\,];\C{ information about names }\6
\&{extern} \&{name\_pointer} \\{name\_dir\_end};\C{ end of \PB{\\{name\_dir}} }%
\6
\&{extern} \&{name\_pointer} \\{name\_ptr};\C{ first unused position in \PB{%
\\{byte\_start}} }\6
\&{extern} \&{char} ${}{*}\\{byte\_ptr}{}$;\C{ first unused position in \PB{%
\\{byte\_mem}} }\6
\&{extern} \&{name\_pointer} \\{hash}[\,];\C{ heads of hash lists }\6
\&{extern} \&{hash\_pointer} \\{hash\_end};\C{ end of \PB{\\{hash}} }\6
\&{extern} \&{hash\_pointer} \|h;\C{ index into hash-head array }\6
\&{extern} \&{name\_pointer} \\{id\_lookup}(\,);\C{ looks up a string in the
identifier table }\6
\&{extern} \&{name\_pointer} \\{section\_lookup}(\,);\C{ finds section name }\6
\&{extern} \&{void} \\{print\_section\_name}(\,)${},{}$ \\{sprint\_section%
\_name}(\,);\par
\fi

\M{12}Code related to error handling:
\Y\B\4\D$\\{spotless}$ \5
\T{0}\C{ \PB{\\{history}} value for normal jobs }\par
\B\4\D$\\{harmless\_message}$ \5
\T{1}\C{ \PB{\\{history}} value when non-serious info was printed }\par
\B\4\D$\\{error\_message}$ \5
\T{2}\C{ \PB{\\{history}} value when an error was noted }\par
\B\4\D$\\{fatal\_message}$ \5
\T{3}\C{ \PB{\\{history}} value when we had to stop prematurely }\par
\B\4\D$\\{mark\_harmless}$ \6
${}\{{}$\1\6
\&{if} ${}(\\{history}\E\\{spotless}){}$\1\5
${}\\{history}\K\\{harmless\_message};{}$\2\6
\4${}\}{}$\2\par
\B\4\D$\\{mark\_error}$ \5
$\\{history}\K{}$\\{error\_message}\par
\B\4\D$\\{confusion}(\|s)$ \5
$\\{fatal}(\.{"!\ This\ can't\ happen}\)\.{:\ "},\39\|s{}$)\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \\{history};\C{ indicates how bad this run was }\6
\&{extern} \\{err\_print}(\,);\C{ print error message and context }\6
\&{extern} \\{wrap\_up}(\,);\C{ indicate \PB{\\{history}} and exit }\6
\&{extern} \&{void} \\{fatal}(\,);\C{ issue error message and die }\6
\&{extern} \&{void} \\{overflow}(\,);\C{ succumb because a table has overflowed
}\par
\fi

\M{13}Code related to file handling:
\Y\B\F\\{line} \5
\|x\C{ make \PB{\\{line}} an unreserved word }\par
\B\4\D$\\{max\_file\_name\_length}$ \5
\T{128}\par
\B\4\D$\\{cur\_file}$ \5
\\{file}[\\{include\_depth}]\C{ current file }\par
\B\4\D$\\{cur\_file\_name}$ \5
\\{file\_name}[\\{include\_depth}]\C{ current file name }\par
\B\4\D$\\{web\_file\_name}$ \5
\\{file\_name}[\T{0}]\C{ main source file name }\par
\B\4\D$\\{cur\_line}$ \5
\\{line}[\\{include\_depth}]\C{ number of current line in current file }\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \\{include\_depth};\C{ current level of nesting }\6
\&{extern} \&{FILE} ${}{*}\\{file}[\,]{}$;\C{ stack of non-change files }\6
\&{extern} \&{FILE} ${}{*}\\{change\_file}{}$;\C{ change file }\6
\&{extern} \&{char} \\{C\_file\_name}[\,];\C{ name of \PB{\\{C\_file}} }\6
\&{extern} \&{char} \\{tex\_file\_name}[\,];\C{ name of \PB{\\{tex\_file}} }\6
\&{extern} \&{char} \\{idx\_file\_name}[\,];\C{ name of \PB{\\{idx\_file}} }\6
\&{extern} \&{char} \\{scn\_file\_name}[\,];\C{ name of \PB{\\{scn\_file}} }\6
\&{extern} \&{char} \\{file\_name}[\,][\\{max\_file\_name\_length}];\C{ stack
of non-change file names }\6
\&{extern} \&{char} \\{change\_file\_name}[\,];\C{ name of change file }\6
\&{extern} \\{line}[\,];\C{ number of current line in the stacked files }\6
\&{extern} \\{change\_line};\C{ number of current line in change file }\6
\&{extern} \&{boolean} \\{input\_has\_ended};\C{ if there is no more input }\6
\&{extern} \&{boolean} \\{changing};\C{ if the current line is from \PB{%
\\{change\_file}} }\6
\&{extern} \&{boolean} \\{web\_file\_open};\C{ if the web file is being read }\6
\&{extern} \\{reset\_input}(\,);\C{ initialize to read the web file and change
file }\6
\&{extern} \\{get\_line}(\,);\C{ inputs the next line }\6
\&{extern} \\{check\_complete}(\,);\C{ checks that all changes were picked up }%
\par
\fi

\M{14}Code related to section numbers:
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{typedef} \&{unsigned} \&{short} \&{sixteen\_bits};\6
\&{extern} \&{sixteen\_bits} \\{section\_count};\C{ the current section number
}\6
\&{extern} \&{boolean} \\{changed\_section}[\,];\C{ is the section changed? }\6
\&{extern} \&{boolean} \\{change\_pending};\C{ is a decision about change still
unclear? }\6
\&{extern} \&{boolean} \\{print\_where};\C{ tells \.{CTANGLE} to print line and
file info }\par
\fi

\M{15}Code related to command line arguments:
\Y\B\4\D$\\{show\_banner}$ \5
\\{flags}[\.{'b'}]\C{ should the banner line be printed? }\par
\B\4\D$\\{show\_progress}$ \5
\\{flags}[\.{'p'}]\C{ should progress reports be printed? }\par
\B\4\D$\\{show\_happiness}$ \5
\\{flags}[\.{'h'}]\C{ should lack of errors be announced? }\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \&{int} \\{argc};\C{ copy of \PB{\\{ac}} parameter to \PB{\\{main}}
}\6
\&{extern} \&{char} ${}{*}{*}\\{argv}{}$;\C{ copy of \PB{\\{av}} parameter to %
\PB{\\{main}} }\6
\&{extern} \&{boolean} \\{flags}[\,];\C{ an option for each 7-bit code }\par
\fi

\M{16}Code relating to output:
\Y\B\4\D$\\{update\_terminal}$ \5
\\{fflush}(\\{stdout})\C{ empty the terminal output buffer }\par
\B\4\D$\\{new\_line}$ \5
\\{putchar}(\.{'\\n'})\par
\B\4\D$\\{putxchar}$ \5
\\{putchar}\par
\B\4\D$\\{term\_write}(\|a,\|b)$ \5
$\\{fflush}(\\{stdout}),\39\\{fwrite}(\|a,\39\&{sizeof}(\&{char}),\39\|b,\39%
\\{stdout}{}$)\par
\B\4\D$\\{C\_printf}(\|c,\|a)$ \5
$\\{fprintf}(\\{C\_file},\39\|c,\39\|a{}$)\par
\B\4\D$\\{C\_putc}(\|c)$ \5
$\\{putc}(\|c,\39\\{C\_file}{}$)\par
\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \&{FILE} ${}{*}\\{C\_file}{}$;\C{ where output of \.{CTANGLE} goes }%
\6
\&{extern} \&{FILE} ${}{*}\\{tex\_file}{}$;\C{ where output of \.{CWEAVE} goes
}\6
\&{extern} \&{FILE} ${}{*}\\{idx\_file}{}$;\C{ where index from \.{CWEAVE} goes
}\6
\&{extern} \&{FILE} ${}{*}\\{scn\_file}{}$;\C{ where list of sections from %
\.{CWEAVE} goes }\6
\&{extern} \&{FILE} ${}{*}\\{active\_file}{}$;\C{ currently active file for %
\.{CWEAVE} output }\par
\fi

\M{17}The procedure that gets everything rolling:

\Y\B\4\X7:Common code for \.{CWEAVE} and \.{CTANGLE}\X${}\mathrel+\E{}$\6
\&{extern} \&{void} \\{common\_init}(\,);\par
\fi

\N{1}{18}Data structures exclusive to {\tt CTANGLE}.
We've already seen that the \PB{\\{byte\_mem}} array holds the names of
identifiers,
strings, and sections;
the \PB{\\{tok\_mem}} array holds the replacement texts
for sections. Allocation is sequential, since things are deleted only
during Phase II, and only in a last-in-first-out manner.

A \&{text} variable is a structure containing a pointer into
\PB{\\{tok\_mem}}, which tells where the corresponding text starts, and an
integer \PB{\\{text\_link}}, which, as we shall see later, is used to connect
pieces of text that have the same name.  All the \&{text}s are stored in
the array \PB{\\{text\_info}}, and we use a \PB{\&{text\_pointer}} variable to
refer
to them.

The first position of \PB{\\{tok\_mem}} that is unoccupied by
replacement text is called \PB{\\{tok\_ptr}}, and the first unused location of
\PB{\\{text\_info}} is called \PB{\\{text\_ptr}}.  Thus we usually have the
identity
\PB{$\\{text\_ptr}\MG\\{tok\_start}\E\\{tok\_ptr}$}.

If your machine does not support \PB{\&{unsigned} \&{char}} you should change
the definition of \&{eight\_bits} to \PB{\&{unsigned} \&{short}}.

\Y\B\4\X18:Typedef declarations\X${}\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{tok\_start}{}$;\C{ pointer into \PB{\\{tok\_mem}} }\6
\&{sixteen\_bits} \\{text\_link};\C{ relates replacement texts }\2\6
${}\}{}$ \&{text};\6
\&{typedef} \&{text} ${}{*}\&{text\_pointer}{}$;\par
\As31, 130, 181\ETs184.
\U1.\fi

\M{19}\B\X19:Global variables\X${}\E{}$\6
\&{text} \\{text\_info}[\\{max\_texts}];\6
\&{text\_pointer} \\{text\_info\_end}${}\K\\{text\_info}+\\{max\_texts}-%
\T{1};{}$\6
\&{text\_pointer} \\{text\_ptr};\C{ first unused position in \PB{\\{text%
\_info}} }\6
\&{eight\_bits} \\{tok\_mem}[\\{max\_toks}];\6
\&{eight\_bits} ${}{*}\\{tok\_mem\_end}\K\\{tok\_mem}+\\{max\_toks}-\T{1};{}$\6
\&{eight\_bits} ${}{*}\\{tok\_ptr}{}$;\C{ first unused position in \PB{\\{tok%
\_mem}} }\par
\As25, 27, 32, 38, 42, 44, 49, 57, 66, 74, 79, 82, 85, 99, 107, 124, 126, 131,
144, 167, 169, 175, 182, 185, 191, 204, 205, 209, 225, 231\ETs237.
\U1.\fi

\M{20}\B\X20:Set initial values\X${}\E{}$\6
$\\{text\_info}\MG\\{tok\_start}\K\\{tok\_ptr}\K\\{tok\_mem};{}$\6
${}\\{text\_ptr}\K\\{text\_info}+\T{1};{}$\6
${}\\{text\_ptr}\MG\\{tok\_start}\K\\{tok\_mem}{}$;\C{ this makes replacement
text 0 of length zero }\par
\As22, 28, 45, 58, 75, 80, 83, 95, 125, 127, 132, 170\ETs192.
\U5.\fi

\M{21}If \PB{\|p} is a pointer to a section name, \PB{$\|p\MG\\{equiv}$} is a
pointer to its
replacement text, an element of the array \PB{\\{text\_info}}.

\Y\B\4\D$\\{equiv}$ \5
\\{equiv\_or\_xref}\C{ info corresponding to names }\par
\fi

\M{22}\B\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{name\_dir}\MG\\{equiv}\K{}$(\&{char} ${}{*}){}$ \\{text\_info};\C{ the
undefined section has no replacement text }\par
\fi

\M{23}Here's the procedure that decides whether a name of length \PB{\|l}
starting at position \PB{\\{first}} equals the identifier pointed to by \PB{%
\|p}:

\Y\B\&{int} ${}\\{names\_match}(\|p,\39\\{first},\39\|l){}$\1\1\6
\&{name\_pointer} \|p;\C{ points to the proposed match }\6
\&{char} ${}{*}\\{first}{}$;\C{ position of first character of string }\6
\&{int} \|l;\C{ length of identifier }\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{length}(\|p)\I\|l){}$\1\5
\&{return} \T{0};\2\6
\&{return} ${}\R\\{strncmp}(\\{first},\39\|p\MG\\{byte\_start},\39\|l);{}$\6
\4${}\}{}$\2\par
\fi

\M{24}The common lookup routine refers to separate routines \PB{\\{init\_node}}
and
\PB{\\{init\_p}} when the data structure grows. Actually \PB{\\{init\_p}} is
called only by
\.{CWEAVE}, but we need to declare a dummy version so that
the loader won't complain of its absence.

\Y\B\&{void} \\{init\_node}(\\{node})\1\1\6
\&{name\_pointer} \\{node};\2\2\6
${}\{{}$\1\6
${}\\{node}\MG\\{equiv}\K{}$(\&{char} ${}{*}){}$ \\{text\_info};\6
\4${}\}{}$\2\7
\&{void} \\{init\_p}(\,)\1\1\2\2\6
${}\{\,\}{}$\par
\fi

\M{25}%mine
Some identifiers are used very often, so their indices in \PB{\\{name\_dir}}
are cached. This is done by inserting them at the very beginning so
that their id numbers will start with~1.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{enum} ${}\{{}$\1\6
${}\\{id\_global}\K\T{1},\39\\{id\_export},\39\\{id\_shared},\39\\{id%
\_chapter},\39\\{id\_transitively},\39\\{id\_import},\39\\{id\_from},\39\\{id%
\_program},\39\\{id\_library},\39\\{id\_enum},\39\\{id\_union},\39\\{id%
\_class},\39\\{id\_struct},\39\\{id\_typedef},\39\\{id\_inline},\39\\{id%
\_extern},\39\\{id\_void},\39\\{id\_int},\39\\{id\_static},\39\\{id\_ifndef},%
\39\\{id\_endif},\39\\{id\_operator},\39\\{id\_mark},\39\\{id\_copy},\39\\{id%
\_paste}{}$\2\6
${}\};{}$\6
\&{char} ${}{*}\\{predefined\_name}[\,]\K\{\.{"global"},\39\.{"export"},\39%
\.{"shared"},\39\.{"chapter"},\39\.{"transitively"},\39\.{"import"},\39%
\.{"from"},\39\.{"program"},\39\.{"library"},\39\.{"enum"},\39\.{"union"},\39%
\.{"class"},\39\.{"struct"},\39\.{"typedef"},\39\.{"inline"},\39\.{"extern"},%
\39\.{"void"},\39\.{"int"},\39\.{"static"},\39\.{"ifndef"},\39\.{"endif"},\39%
\.{"operator"},\39\.{"mark"},\39\.{"copy"},\39\.{"paste"}\}{}$;\par
\fi

\M{26}%mine
\Y\B\4\D$\\{Number}(\|x)$ \5
(\&{sizeof} (\|x)${}/{}$\&{sizeof} ${}({*}(\|x)){}$)\par
\Y\B\4\X26:Insert predefined identifiers into \PB{\\{name\_dir}}\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|i;\7
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{Number}(\\{predefined\_name});{}$ ${}\|i%
\PP){}$\1\5
${}\\{id\_lookup}(\\{predefined\_name}[\|i],\39\\{predefined\_name}[\|i]+%
\\{strlen}(\\{predefined\_name}[\|i]),\39\T{0});{}$\2\6
\4${}\}{}$\2\par
\U5.\fi

\N{1}{27}Tokens.
Replacement texts, which represent \CEE/ code in a compressed format,
appear in \PB{\\{tok\_mem}} as mentioned above. The codes in
these texts are called `tokens'; some tokens occupy two consecutive
eight-bit byte positions, and the others take just one byte.

If $p$ points to a replacement text, \PB{$\|p\MG\\{tok\_start}$} is the \PB{%
\\{tok\_mem}} position
of the first eight-bit code of that text. If \PB{$\|p\MG\\{text\_link}\E%
\T{0}$},
this is the replacement text for a macro, otherwise it is the replacement
text for a section. In the latter case \PB{$\|p\MG\\{text\_link}$} is either
equal to
\PB{\\{section\_flag}}, which means that there is no further text for this
section, or
\PB{$\|p\MG\\{text\_link}$} points to a continuation of this replacement text;
such
links are created when several sections have \CEE/ texts with the same
name, and they also tie together all the \CEE/ texts of unnamed sections.
The replacement text pointer for the first unnamed section appears in
\PB{$\\{text\_info}\MG\\{text\_link}$}, and the most recent such pointer is %
\PB{\\{last\_unnamed}}.

\Y\B\4\D$\\{section\_flag}$ \5
\\{max\_texts}\C{ final \PB{\\{text\_link}} in section replacement texts }\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{text\_pointer} \\{last\_unnamed};\C{ most recent replacement text of unnamed
section }\par
\fi

\M{28}\B\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{last\_unnamed}\K\\{text\_info};{}$\6
${}\\{text\_info}\MG\\{text\_link}\K\T{0}{}$;\par
\fi

\M{29}If the first byte of a token is less than \PB{\T{\~200}}, the token
occupies a
single byte. Otherwise we make a sixteen-bit token by combining two consecutive
bytes \PB{\|a} and \PB{\|b}. If \PB{$\T{\~200}\Z\|a<\T{\~250}$}, then \PB{$(%
\|a-\T{\~200})\hbox{${}\times2^8$}+\|b$}
points to an identifier; if \PB{$\T{\~250}\Z\|a<\T{\~320}$}, then
\PB{$(\|a-\T{\~250})\hbox{${}\times2^8$}+\|b$} points to a section name
(or, if it has the special value \PB{\\{output\_defs\_flag}},
to the area where the preprocessor definitions are stored); and if
\PB{$\T{\~320}\Z\|a<\T{\~400}$}, then \PB{$(\|a-\T{\~320})\hbox{${}\times2^8$}+%
\|b$} is the number of the section
in which the current replacement text appears.

Codes less than \PB{\T{\~200}} are 7-bit \PB{\&{char}} codes that represent
themselves.
Some of the 7-bit codes will not be present, however, so we can
use them for special purposes. The following symbolic names are used:

\yskip \hang \PB{\\{join}} denotes the concatenation of adjacent items with no
space or line breaks allowed between them (the \.{@\&} operation of \.{CWEB}).

\hang \PB{\\{string}} denotes the beginning or end of a string, verbatim
construction or numerical constant.

\Y\B\4\D$\\{string}$ \5
\T{\~2}\C{ takes the place of extended ASCII \.{\char2} }\par
\B\4\D$\\{join}$ \5
\T{\~177}\C{ takes the place of ASCII delete }\par
\B\4\D$\\{output\_defs\_flag}$ \5
$(\T{2}*\T{\~24000}-\T{1}{}$)\par
\fi

\M{30}The following procedure is used to enter a two-byte value into
\PB{\\{tok\_mem}} when a replacement text is being generated.

\Y\B\&{void} \\{store\_two\_bytes}(\|x)\1\1\6
\&{sixteen\_bits} \|x;\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{tok\_ptr}+\T{2}>\\{tok\_mem\_end}){}$\1\5
\\{overflow}(\.{"token"});\2\6
${}{*}\\{tok\_ptr}\PP\K\|x\GG\T{8}{}$;\C{ store high byte }\6
${}{*}\\{tok\_ptr}\PP\K\|x\AND\T{\~377}{}$;\C{ store low byte }\6
\4${}\}{}$\2\par
\fi

\N{0}{31}Stacks for output.  The output process uses a stack to keep track
of what is going on at different ``levels'' as the sections are being
written out.  Entries on this stack have five parts:

\yskip\hang \PB{\\{end\_field}} is the \PB{\\{tok\_mem}} location where the
replacement
text of a particular level will end;

\hang \PB{\\{byte\_field}} is the \PB{\\{tok\_mem}} location from which the
next token
on a particular level will be read;

\hang \PB{\\{name\_field}} points to the name corresponding to a particular
level;

\hang \PB{\\{repl\_field}} points to the replacement text currently being read
at a particular level;

\hang \PB{\\{section\_field}} is the section number, or zero if this is a
macro.

\yskip\noindent The current values of these five quantities are referred to
quite frequently, so they are stored in a separate place instead of in
the \PB{\\{stack}} array. We call the current values \PB{\\{cur\_end}}, \PB{%
\\{cur\_byte}},
\PB{\\{cur\_name}}, \PB{\\{cur\_repl}}, and \PB{\\{cur\_section}}.

The global variable \PB{\\{stack\_ptr}} tells how many levels of output are
currently in progress. The end of all output occurs when the stack is
empty, i.e., when \PB{$\\{stack\_ptr}\E\\{stack}$}.

\Y\B\4\X18:Typedef declarations\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{end\_field}{}$;\C{ ending location of replacement text
}\6
\&{eight\_bits} ${}{*}\\{byte\_field}{}$;\C{ present location within
replacement text }\6
\&{name\_pointer} \\{name\_field};\C{ \PB{\\{byte\_start}} index for text being
output }\6
\&{text\_pointer} \\{repl\_field};\C{ \PB{\\{tok\_start}} index for text being
output }\6
\&{sixteen\_bits} \\{section\_field};\C{ section number or zero if not a
section }\2\6
${}\}{}$ \&{output\_state};\6
\&{typedef} \&{output\_state} ${}{*}\&{stack\_pointer}{}$;\par
\fi

\M{32}\B\D$\\{cur\_end}$ \5
$\\{cur\_state}.{}$\\{end\_field}\C{ current ending location in \PB{\\{tok%
\_mem}} }\par
\B\4\D$\\{cur\_byte}$ \5
$\\{cur\_state}.{}$\\{byte\_field}\C{ location of next output byte in \PB{%
\\{tok\_mem}}}\par
\B\4\D$\\{cur\_name}$ \5
$\\{cur\_state}.{}$\\{name\_field}\C{ pointer to current name being expanded }%
\par
\B\4\D$\\{cur\_repl}$ \5
$\\{cur\_state}.{}$\\{repl\_field}\C{ pointer to current replacement text }\par
\B\4\D$\\{cur\_section}$ \5
$\\{cur\_state}.{}$\\{section\_field}\C{ current section number being expanded
}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{output\_state} \\{cur\_state};\C{ \PB{\\{cur\_end}}, \PB{\\{cur\_byte}}, %
\PB{\\{cur\_name}}, \PB{\\{cur\_repl}}   and \PB{\\{cur\_section}} }\6
\&{output\_state} ${}\\{stack}[\\{stack\_size}+\T{1}]{}$;\C{ info for
non-current levels }\6
\&{stack\_pointer} \\{stack\_ptr};\C{ first unused location in the output state
stack }\6
\&{stack\_pointer} \\{stack\_end}${}\K\\{stack}+\\{stack\_size}{}$;\C{ end of %
\PB{\\{stack}} }\par
\fi

\M{33}To get the output process started, we will perform the following
initialization steps. We may assume that \PB{$\\{text\_info}\MG\\{text\_link}$}
is nonzero,
since it points to the \CEE/ text in the first unnamed section that generates
code; if there are no such sections, there is nothing to output, and an
error message will have been generated before we do any of the initialization.

\Y\B\4\X33:Initialize the output stacks\X${}\E{}$\6
$\\{stack\_ptr}\K\\{stack}+\T{1};{}$\6
${}\\{cur\_name}\K\\{name\_dir};{}$\6
${}\\{cur\_repl}\K\\{text\_info}\MG\\{text\_link}+\\{text\_info};{}$\6
${}\\{cur\_byte}\K\\{cur\_repl}\MG\\{tok\_start};{}$\6
\\{set\_cur\_end}(\,);\6
${}\\{cur\_section}\K\T{0}{}$;\par
\U48.\fi

\M{34}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{set\_cur\_end}(\,);\par
\fi

\M{35}The current token list ends where the next \PB{\&{text}} starts.
There is one exception to the rule. Since one token list can be the
content of two different consecutive \PB{\&{text}} sections
(e.g.~a shared and an export section)
we have to find the next \PB{\&{text}} that points to a different position in
the token list.
\Y\B\&{void} \\{set\_cur\_end}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{text\_pointer} \\{tp};\7
\&{for} ${}(\\{tp}\K\\{cur\_repl};{}$ ${}\PP\\{tp}\Z\\{text\_ptr};{}$ \,)\5
${}\{{}$\1\6
\&{if} ${}(\\{cur\_repl}\MG\\{tok\_start}\I\\{tp}\MG\\{tok\_start}){}$\5
${}\{{}$\1\6
${}\\{cur\_end}\K\\{tp}\MG\\{tok\_start};{}$\6
\&{return};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{cur\_end}\K(\\{cur\_repl}+\T{1})\MG\\{tok\_start};{}$\6
\4${}\}{}$\2\par
\fi

\M{36}When the replacement text for name \PB{\|p} is to be inserted into the
output,
the following subroutine is called to save the old level of output and get
the new one going.

We assume that the \CEE/ compiler can copy structures.

\Y\B\&{void} \\{push\_level}(\|p)\C{ suspends the current level }\1\1\6
\&{name\_pointer} \|p;\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{stack\_ptr}\E\\{stack\_end}){}$\1\5
\\{overflow}(\.{"stack"});\2\6
${}{*}\\{stack\_ptr}\K\\{cur\_state};{}$\6
${}\\{stack\_ptr}\PP;{}$\6
\&{if} ${}(\|p\I\NULL){}$\5
${}\{{}$\C{ \PB{$\|p\E\NULL$} means we are in \PB{\\{output\_defs}} }\1\6
${}\\{cur\_name}\K\|p;{}$\6
${}\\{cur\_repl}\K{}$(\&{text\_pointer}) \|p${}\MG\\{equiv};{}$\6
${}\\{cur\_byte}\K\\{cur\_repl}\MG\\{tok\_start};{}$\6
\\{set\_cur\_end}(\,);\6
${}\\{cur\_section}\K\T{0};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{37}When we come to the end of a replacement text, the \PB{\\{pop\_level}}
subroutine
does the right thing: It either moves to the continuation of this replacement
text or returns the state to the most recently stacked level.

\Y\B\&{void} \\{pop\_level}(\\{flag})\C{ do this when \PB{\\{cur\_byte}}
reaches \PB{\\{cur\_end}} }\1\1\6
\&{int} \\{flag};\C{ \PB{$\\{flag}\E\T{0}$} means we are in \PB{\\{output%
\_defs}} }\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{flag}\W\\{cur\_repl}\MG\\{text\_link}<\\{section\_flag}){}$\5
${}\{{}$\C{ link to a continuation }\1\6
${}\\{cur\_repl}\K\\{cur\_repl}\MG\\{text\_link}+\\{text\_info}{}$;\C{ stay on
the same level }\6
${}\\{cur\_byte}\K\\{cur\_repl}\MG\\{tok\_start};{}$\6
\\{set\_cur\_end}(\,);\6
\&{return};\6
\4${}\}{}$\2\6
${}\\{stack\_ptr}\MM{}$;\C{ go down to the previous level }\6
\&{if} ${}(\\{stack\_ptr}>\\{stack}){}$\1\5
${}\\{cur\_state}\K{*}\\{stack\_ptr};{}$\2\6
\4${}\}{}$\2\par
\fi

\M{38}The heart of the output procedure is the function \PB{\\{get\_output}},
which produces the next token of output and sends it on to the lower-level
function \PB{\\{out\_char}}. The main purpose of \PB{\\{get\_output}} is to
handle the
necessary stacking and unstacking. It sends the value \PB{\\{section\_number}}
if the next output begins or ends the replacement text of some section,
in which case \PB{\\{cur\_val}} is that section's number (if beginning) or the
negative of that value (if ending). (A section number of 0 indicates
not the beginning or ending of a section, but a \&{\#line} command.)
And it sends the value \PB{\\{identifier}}
if the next output is an identifier, in which case
\PB{\\{cur\_val}} points to that identifier name.

\Y\B\4\D$\\{section\_number}$ \5
\T{\~201}\C{ code returned by \PB{\\{get\_output}} for section numbers }\par
\B\4\D$\\{identifier}$ \5
\T{\~202}\C{ code returned by \PB{\\{get\_output}} for identifiers }\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{cur\_val};\C{ additional information corresponding to output token }%
\par
\fi

\M{39}If \PB{\\{get\_output}} finds that no more output remains, it returns
with
\PB{$\\{stack\_ptr}\E\\{stack}$}.

\Y\B\&{void} \\{get\_output}(\,)\C{ sends next token to \PB{\\{out\_char}} }\6
${}\{{}$\1\6
\&{sixteen\_bits} \|a;\C{ value of current byte }\7
\4\\{restart}:\6
\&{if} ${}(\\{stack\_ptr}\E\\{stack}){}$\1\5
\&{return};\2\6
\&{if} ${}(\\{cur\_byte}\E\\{cur\_end}){}$\5
${}\{{}$\1\6
${}\\{cur\_val}\K{-}{}$((\&{int}) \\{cur\_section});\C{ cast needed because of
sign extension }\6
\\{pop\_level}(\T{1});\6
\&{if} ${}(\\{cur\_val}\E\T{0}){}$\1\5
\&{goto} \\{restart};\2\6
\\{out\_char}(\\{section\_number});\6
\&{return};\6
\4${}\}{}$\2\6
${}\|a\K{*}\\{cur\_byte}\PP;{}$\6
\&{if} ${}(\\{out\_state}\E\\{verbatim}\W\|a\I\\{string}\W\|a\I\\{constant}\W%
\|a\I\.{'\\n'}){}$\1\5
\\{C\_putc}(\|a);\C{ a high-bit character can occur in a string }\2\6
\&{else} \&{if} ${}(\|a<\T{\~200}){}$\1\5
\\{out\_char}(\|a);\C{ one-byte token }\2\6
\&{else}\5
${}\{{}$\1\6
${}\|a\K(\|a-\T{\~200})*\T{\~400}+{*}\\{cur\_byte}\PP;{}$\6
\&{switch} ${}(\|a/\T{\~24000}){}$\5
${}\{{}$\C{ \PB{$\T{\~24000}\E(\T{\~250}-\T{\~200})*\T{\~400}$} }\1\6
\4\&{case} \T{0}:\5
${}\\{cur\_val}\K\|a;{}$\6
\\{out\_char}(\\{identifier});\6
\&{break};\6
\4\&{case} \T{1}:\6
\&{if} ${}(\|a\E\\{output\_defs\_flag}){}$\1\5
\\{output\_defs}(\,);\2\6
\&{else}\1\5
\X40:Expand section \PB{$\|a-\T{\~24000}$}, \PB{\&{goto} \\{restart}}\X;\2\6
\&{break};\6
\4\&{default}:\5
${}\\{cur\_val}\K\|a-\T{\~50000};{}$\6
\&{if} ${}(\\{cur\_val}>\T{0}){}$\1\5
${}\\{cur\_section}\K\\{cur\_val};{}$\2\6
\\{out\_char}(\\{section\_number});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{40}The user may have forgotten to give any \CEE/ text for a section name,
or the \CEE/ text may have been associated with a different name by mistake.

\Y\B\4\X40:Expand section \PB{$\|a-\T{\~24000}$}, \PB{\&{goto} \\{restart}}%
\X${}\E{}$\6
${}\{{}$\1\6
${}\|a\MRL{-{\K}}\T{\~24000};{}$\6
\&{if} ${}((\|a+\\{name\_dir})\MG\\{equiv}\I{}$(\&{char} ${}{*}){}$ \\{text%
\_info})\1\5
${}\\{push\_level}(\|a+\\{name\_dir});{}$\2\6
\&{else} \&{if} ${}(\|a\I\T{0}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"\\n!\ Not\ present:\ <"});\6
${}\\{print\_section\_name}(\|a+\\{name\_dir});{}$\6
\\{err\_print}(\.{">"});\6
\4${}\}{}$\2\6
\&{goto} \\{restart};\6
\4${}\}{}$\2\par
\U39.\fi

\N{1}{41}Producing the output.
The \PB{\\{get\_output}} routine above handles most of the complexity of output
generation, but there are two further considerations that have a nontrivial
effect on \.{CTANGLE}'s algorithms.

\fi

\M{42}First,
we want to make sure that the output has spaces and line breaks in
the right places (e.g., not in the middle of a string or a constant or an
identifier, not at a `\.{@\&}' position
where quantities are being joined together, and certainly after an \.=
because the \CEE/ compiler thinks \.{=-} is ambiguous).

The output process can be in one of following states:

\yskip\hang \PB{\\{num\_or\_id}} means that the last item in the buffer is a
number or
identifier, hence a blank space or line break must be inserted if the next
item is also a number or identifier.

\yskip\hang \PB{\\{unbreakable}} means that the last item in the buffer was
followed
by the \.{@\&} operation that inhibits spaces between it and the next item.

\yskip\hang \PB{\\{verbatim}} means we're copying only character tokens, and
that they are to be output exactly as stored.  This is the case during
strings, verbatim constructions and numerical constants.

\yskip\hang \PB{\\{post\_slash}} means we've just output a slash.

\yskip\hang \PB{\\{normal}} means none of the above.

\yskip\noindent Furthermore, if the variable \PB{\\{protect}} is positive,
newlines
are preceded by a `\.\\'.

\Y\B\4\D$\\{normal}$ \5
\T{0}\C{ non-unusual state }\par
\B\4\D$\\{num\_or\_id}$ \5
\T{1}\C{ state associated with numbers and identifiers }\par
\B\4\D$\\{post\_slash}$ \5
\T{2}\C{ state following a \./ }\par
\B\4\D$\\{unbreakable}$ \5
\T{3}\C{ state associated with \.{@\&} }\par
\B\4\D$\\{verbatim}$ \5
\T{4}\C{ state in the middle of a string }\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{eight\_bits} \\{out\_state};\C{ current status of partial output }\6
\&{boolean} \\{protect};\C{ should newline characters be quoted? }\par
\fi

\M{43}Here is a routine that is invoked when we want to output the current
line.
During the output process, \PB{\\{cur\_line}} equals the number of the next
line
to be output.

\Y\B\&{void} \\{flush\_buffer}(\,)\C{ writes one line to output file }\6
${}\{{}$\1\6
\\{C\_putc}(\.{'\\n'});\6
\&{if} ${}(\\{cur\_line}\MOD\T{100}\E\T{0}\W\\{show\_progress}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"."});\6
\&{if} ${}(\\{cur\_line}\MOD\T{500}\E\T{0}){}$\1\5
${}\\{printf}(\.{"\%d"},\39\\{cur\_line});{}$\2\6
\\{update\_terminal};\C{ progress report }\6
\4${}\}{}$\2\6
${}\\{cur\_line}\PP;{}$\6
\4${}\}{}$\2\par
\fi

\M{44}Second, we have modified the original \.{TANGLE} so that it will write
output
on multiple files.
If a section name is introduced in at least one place by \.{@(}
instead of \.{@<}, we treat it as the name of a file.
All these special sections are saved on a stack, \PB{\\{output\_files}}.
We write them out after we've done the unnamed section.

\Y\B\4\D$\\{max\_files}$ \5
\T{256}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{name\_pointer} \\{output\_files}[\\{max\_files}];\6
\&{name\_pointer} ${}{*}\\{cur\_out\_file},{}$ ${}{*}\\{end\_output\_files},{}$
${}{*}\\{an\_output\_file};{}$\6
\&{char} \\{cur\_section\_name\_char};\C{ is it \PB{\.{'<'}} or \PB{\.{'('}} }\6
\&{char} \\{output\_file\_name}[\\{longest\_name}];\C{ name of the file }\par
\fi

\M{45}We make \PB{\\{end\_output\_files}} point just beyond the end of
\PB{\\{output\_files}}. The stack pointer
\PB{\\{cur\_out\_file}} starts out there. Every time we see a new file, we
decrement \PB{\\{cur\_out\_file}} and then write it in.
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{cur\_out\_file}\K\\{end\_output\_files}\K\\{output\_files}+\\{max%
\_files}{}$;\par
\fi

\M{46}\B\X46:If it's not there, add \PB{\\{cur\_section\_name}} to the output
file stack, or complain we're out of room\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\\{an\_output\_file}\K\\{cur\_out\_file};{}$ ${}\\{an\_output%
\_file}<\\{end\_output\_files};{}$ ${}\\{an\_output\_file}\PP){}$\1\6
\&{if} ${}({*}\\{an\_output\_file}\E\\{cur\_section\_name}){}$\1\5
\&{break};\2\2\6
\&{if} ${}(\\{an\_output\_file}\E\\{end\_output\_files}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{cur\_out\_file}>\\{output\_files}){}$\1\5
${}{*}\MM\\{cur\_out\_file}\K\\{cur\_section\_name};{}$\2\6
\&{else}\5
${}\{{}$\1\6
\\{overflow}(\.{"output\ files"});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U94.\fi

\N{1}{47}The big output switch.  Here then is the routine that does the
output.

\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{phase\_two}(\,);\par
\fi

\M{48}%modified
\Y\B\&{void} \\{phase\_two}(\,)\1\1\2\2\6
${}\{{}$\1\6
${}\\{web\_file\_open}\K\T{0};{}$\6
${}\\{cur\_line}\K\T{1};{}$\6
\X33:Initialize the output stacks\X;\6
\X50:Open the export files if necessary\X;\6
\X56:Output macro definitions if appropriate\X;\6
\&{if} ${}(\\{text\_info}\MG\\{text\_link}\E\T{0}\W\\{cur\_out\_file}\E\\{end%
\_output\_files}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"\\n!\ No\ program\ text}\)\.{\ was\ specified."});\6
\\{mark\_harmless};\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{cur\_out\_file}\E\\{end\_output\_files}){}$\5
${}\{{}$\1\6
\&{if} (\\{show\_progress})\1\5
${}\\{printf}(\.{"\\nWriting\ the\ outpu}\)\.{t\ file\ (\%s):"},\39\\{C\_file%
\_name});{}$\2\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} (\\{show\_progress})\5
${}\{{}$\1\6
\\{printf}(\.{"\\nWriting\ the\ outpu}\)\.{t\ files:"});\6
${}\\{printf}(\.{"\ (\%s)"},\39\\{C\_file\_name});{}$\6
\\{update\_terminal};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{text\_info}\MG\\{text\_link}\E\T{0}){}$\1\5
\&{goto} \\{writeloop};\2\6
\4${}\}{}$\2\6
\&{while} ${}(\\{stack\_ptr}>\\{stack}){}$\1\5
\\{get\_output}(\,);\2\6
\\{flush\_buffer}(\,);\6
\4\\{writeloop}:\5
\X55:Write all the named output files\X;\6
\X164:Output all exports\X;\6
\&{if} (\\{show\_happiness})\1\5
\\{printf}(\.{"\\nDone."});\2\6
\4${}\}{}$\2\6
\X51:Close all opened export files\X;\6
\4${}\}{}$\2\par
\fi

\M{49}%mine
As \.{mCTANGLE} now can handle multiple files, it has to export
datatypes, functions and variables to other translation units or
programs. This is done using header files named \.{Exp} for exported data
and \.{Shr} for data shared between different chapters of the same book.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} \\{Exp\_file\_name}[\\{max\_file\_name\_length}];\C{ name of \PB{%
\\{Exp\_file}} }\6
\&{char} \\{Shr\_file\_name}[\\{max\_file\_name\_length}];\C{ name of \PB{%
\\{Shr\_file}} }\6
\&{FILE} ${}{*}\\{Exp\_file};{}$\6
\&{FILE} ${}{*}\\{Shr\_file};{}$\6
\&{FILE} ${}{*}\\{Code\_file}{}$;\C{ The one which really gets the code (former
\CEE/ file) }\par
\fi

\M{50}%mine
We only open the files, if their keywords have appeared during phase one.
This is indicated by the global variable \PB{\\{used\_exports}}.
Anyway, we only open temporary files
as we don't want to overwrite them if they haven't been changed
in order to save compilation time.
\Y\B\4\X50:Open the export files if necessary\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp},{}$ ${}{*}\\{pt},{}$ \\{defname}[\\{max\_file\_name%
\_length}];\7
\&{if} ${}(\\{used\_exports}\AND\\{exp\_export}){}$\5
${}\{{}$\1\6
${}\\{cp}\K\\{exp\_file\_name\_of}(\\{Exp\_file\_name},\39\\{file\_name}[%
\T{0}],\39\.{".\_ex"});{}$\6
\&{if} ${}((\\{Exp\_file}\K\\{fopen}(\\{Exp\_file\_name},\39\.{"w"}))\E%
\NULL){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ open\ tempo}\)\.{rary\ output\ file\ for}\)\.{\
exports\ "},\39\\{Exp\_file\_name});{}$\2\6
${}\\{fprintf}(\\{Exp\_file},\39\.{"/*\ Book:\\"\%s\\",\ Cha}\)\.{pter\ \%d\ */%
\\n"},\39\\{book\_name},\39\\{chapter\_no}+\T{1});{}$\6
${}\\{strcpy}(\\{defname},\39\\{cp});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{defname});{}$\6
\&{if} (\\{cp})\1\5
${}\\{strcpy}(\\{cp},\39\.{".exp"});{}$\2\6
\&{for} ${}(\\{cp}\K\\{defname};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\6
\&{if} ${}(\R\\{isalnum}({*}\\{cp})){}$\1\5
${}{*}\\{cp}\K\.{'\_'};{}$\2\2\6
${}\\{fprintf}(\\{Exp\_file},\39\.{"\#ifndef\ \%s\\n\#define}\)\.{\ \%s\\n"},%
\39\\{defname},\39\\{defname});{}$\6
\\{chapter\_to\_book\_exp}(\,);\C{ \PB{$\#$ \&{include}} goes to book export
file }\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{exp\_file\_name\_of}(\\{Exp\_file\_name},\39\\{file\_name}[\T{0}],\39%
\.{".exp"});{}$\6
\\{remove}(\\{Exp\_file\_name});\C{ delete possible old export file }\6
\4${}\}{}$\2\6
${}\\{strcpy}(\\{Shr\_file\_name},\39\\{file\_name}[\T{0}]);{}$\6
${}\\{pt}\K\\{file\_name\_ext}(\\{Shr\_file\_name});{}$\6
\&{if} (\\{pt})\1\5
${}{*}\\{pt}\K\T{0};{}$\2\6
\&{if} ${}(\\{used\_exports}\AND\\{exp\_shared}){}$\5
${}\{{}$\1\6
${}\\{strcpy}(\\{pt},\39\.{".\_sh"});{}$\6
\&{if} ${}((\\{Shr\_file}\K\\{fopen}(\\{Shr\_file\_name},\39\.{"w"}))\E%
\NULL){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ open\ tempo}\)\.{rary\ output\ file\ for}\)\.{\
shared\ data\ "},\39\\{Shr\_file\_name});{}$\2\6
${}\\{fprintf}(\\{Shr\_file},\39\.{"/*\ Book:\\"\%s\\",\ Cha}\)\.{pter\ \%d\ */%
\\n"},\39\\{book\_name},\39\\{chapter\_no}+\T{1});{}$\6
${}\\{strcpy}(\\{defname},\39\\{Shr\_file\_name});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{defname});{}$\6
\&{if} (\\{cp})\1\5
${}\\{strcpy}(\\{cp},\39\.{".shr"});{}$\2\6
\&{for} ${}(\\{cp}\K\\{defname};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\6
\&{if} ${}(\R\\{isalnum}({*}\\{cp})){}$\1\5
${}{*}\\{cp}\K\.{'\_'};{}$\2\2\6
${}\\{fprintf}(\\{Shr\_file},\39\.{"\#ifndef\ \%s\\n\#define}\)\.{\ \%s\\n"},%
\39\\{defname},\39\\{defname});{}$\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{strcpy}(\\{pt},\39\.{".shr"});{}$\6
\\{remove}(\\{Shr\_file\_name});\6
\4${}\}{}$\2\6
${}\\{Code\_file}\K\\{C\_file}{}$;\C{ save the pointer to the \CEE/ file }\6
\4${}\}{}$\2\par
\U48.\fi

\M{51}%mine
After phase two has completed, we close all opened temporary export files.
We keep those which have changed and destroy the others.
\Y\B\4\X51:Close all opened export files\X${}\E{}$\6
\&{if} (\\{Shr\_file})\5
${}\{{}$\1\6
${}\\{fprintf}(\\{Shr\_file},\39\.{"\#endif\\n"});{}$\6
\\{fclose}(\\{Shr\_file});\6
${}\\{Shr\_file}\K\NULL;{}$\6
${}\\{keep\_exp\_file\_if\_changed}(\.{".shr"},\39\\{Shr\_file\_name}){}$;\C{
keep only if changed }\6
\4${}\}{}$\2\6
\&{if} (\\{Exp\_file})\5
${}\{{}$\1\6
${}\\{fprintf}(\\{Exp\_file},\39\.{"\#endif\\n"});{}$\6
\\{fclose}(\\{Exp\_file});\6
${}\\{Exp\_file}\K\NULL;{}$\6
${}\\{keep\_exp\_file\_if\_changed}(\.{".exp"},\39\\{Exp\_file\_name});{}$\6
\4${}\}{}$\2\par
\U48.\fi

\M{52}%mine
\Y\B\4\X8:Include files\X${}\mathrel+\E{}$\6
\8\#\&{include} \.{<sys/types.h>}\6
\8\#\&{include} \.{<sys/stat.h>}\6
\8\#\&{include} \.{<utime.h>}\par
\fi

\M{53}%mine
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{boolean} \\{keep\_exp\_file\_if\_changed}(\,);\par
\fi

\M{54}%mine
We only keep the temporary export file, if it has changed.
Doing so, we can reduce the turnaround time since rewriting the export
files all the time would cause \.{make} to translate the whole project
even if we only changed a single line in our \.{CWEB} file.

The following function tests, if there are any differences
between the just created temporary file \PB{\\{tmpname}} and a possibly
existing
export file with the same name as \PB{\\{tmpname}} but with the
file extension \PB{\\{suffix}}.

If so, it deletes the old export file and keeps the temporary export file.
If there are no differences or the files only differ in \&{\#line} statements
or comments, which have no influence on the contents of the file itself,
the temporary file gets the date of the old export file and takes its place.

All comments in the file are written by \.{mCTANGLE} itself so we know
that each comment exactly takes one line and starts at the first column.
These comments tell \.{mCWEAVE} where the various parts of the export file
came from. This is the reason why we always want to keep the new temporary
export file and only decide whether to restore the original modification
date. We want to have the comments up to date in order to have \.{mCWEAVE}
make proper references.
\Y\B\&{boolean} ${}\\{keep\_exp\_file\_if\_changed}(\\{suffix},\39%
\\{tmpname}){}$\1\1\6
\&{char} ${}{*}\\{suffix};{}$\6
\&{char} ${}{*}\\{tmpname};\2\2{}$\6
${}\{{}$\1\6
\&{char} \\{expname}[\\{max\_file\_name\_length}]${},{}$ ${}{*}\\{cp};{}$\6
\&{FILE} ${}{*}\\{fp},{}$ ${}{*}\\{tmp};{}$\6
\&{char} ${}{*}\\{c1},{}$ ${}{*}\\{c2};{}$\6
\&{char} \\{buffer}[\T{2}][\T{128}];\6
\&{struct} \\{stat} \|s;\6
\&{struct} \\{utimbuf} \|u;\7
${}\\{strcpy}(\\{expname},\39\\{tmpname});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{expname});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0}{}$;\C{ remove old extension }\2\6
${}\\{strcat}(\\{expname},\39\\{suffix});{}$\6
\\{buffer}[\T{0}][\&{sizeof} (\\{buffer}[\T{0}])${}-\T{1}]\K\\{buffer}[%
\T{1}]{}$[\&{sizeof} (\\{buffer}[\T{0}])${}-\T{1}]\K\.{'\\0'};{}$\6
\&{if} ${}((\\{fp}\K\\{fopen}(\\{expname},\39\.{"r"}))\I\NULL){}$\5
${}\{{}$\1\6
\&{if} ${}((\\{tmp}\K\\{fopen}(\\{tmpname},\39\.{"r"}))\E\NULL){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ reopen\ out}\)\.{put\ file\ for\ input:"},\39%
\\{tmpname});{}$\2\6
\&{do}\5
${}\{{}$\1\6
${}\\{c1}\K\\{fgets}(\\{buffer}[\T{0}],\39{}$\&{sizeof} (\\{buffer}[\T{0}])${}-%
\T{1},\39\\{tmp});{}$\6
${}\\{c2}\K\\{fgets}(\\{buffer}[\T{1}],\39{}$\&{sizeof} (\\{buffer}[\T{1}])${}-%
\T{1},\39\\{fp});{}$\6
\&{if} ${}(\\{c1}\E\NULL\V\\{c2}\E\NULL){}$\1\5
\&{break};\C{ end of file }\2\6
\4${}\}{}$\2\5
\&{while} ${}(\\{strcmp}(\\{buffer}[\T{0}],\39\\{buffer}[\T{1}])\E\T{0}\V(%
\\{strncmp}(\\{buffer}[\T{0}],\39\.{"\#line"},\39\T{5})\E\T{0}\W\\{strncmp}(%
\\{buffer}[\T{1}],\39\.{"\#line"},\39\T{5})\E\T{0})\V(\\{strncmp}(\\{buffer}[%
\T{0}],\39\.{"/*"},\39\T{2})\E\T{0}\W\\{strncmp}(\\{buffer}[\T{1}],\39\.{"/*"},%
\39\T{2})\E\T{0}));{}$\6
\\{fclose}(\\{tmp});\6
\\{fclose}(\\{fp});\6
\&{if} ${}(\\{c1}\E\NULL\W\\{c2}\E\NULL){}$\5
${}\{{}$\C{ file did not change }\1\6
${}\\{stat}(\\{expname},\39{\AND}\|s){}$;\C{ save file date }\6
\\{remove}(\\{expname});\C{ remove old file }\6
${}\\{rename}(\\{tmpname},\39\\{expname}){}$;\C{ new file becomes export file }%
\6
${}\|u.\\{actime}\K\|s.\\{st\_atime};{}$\6
${}\|u.\\{modtime}\K\|s.\\{st\_mtime};{}$\6
${}\\{utime}(\\{expname},\39{\AND}\|u){}$;\C{ reset file date }\6
\&{return} \T{0};\6
\4${}\}{}$\2\6
\\{remove}(\\{expname});\6
\4${}\}{}$\C{ file has changed or did not exist }\2\6
${}\\{rename}(\\{tmpname},\39\\{expname});{}$\6
${}\\{printf}(\.{"\\nExport\ file\ writt}\)\.{en:\ \%s"},\39\\{expname});{}$\6
\&{return} \T{1};\6
\4${}\}{}$\2\par
\fi

\M{55}To write the named output files, we proceed as for unnamed
sections.
The only subtlety is that we have to open each one.

\Y\B\4\X55:Write all the named output files\X${}\E{}$\6
\&{for} ${}(\\{an\_output\_file}\K\\{end\_output\_files};{}$ ${}\\{an\_output%
\_file}>\\{cur\_out\_file};{}$ \,)\5
${}\{{}$\1\6
${}\\{an\_output\_file}\MM;{}$\6
${}\\{sprint\_section\_name}(\\{output\_file\_name},\39{*}\\{an\_output%
\_file});{}$\6
\\{fclose}(\\{C\_file});\6
${}\\{C\_file}\K\\{fopen}(\\{output\_file\_name},\39\.{"w"});{}$\6
\&{if} ${}(\\{C\_file}\E\T{0}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ open\ outpu}\)\.{t\ file:"},\39\\{output\_file%
\_name});{}$\2\6
${}\\{printf}(\.{"\\n(\%s)"},\39\\{output\_file\_name});{}$\6
\\{update\_terminal};\6
${}\\{cur\_line}\K\T{1};{}$\6
${}\\{stack\_ptr}\K\\{stack}+\T{1};{}$\6
${}\\{cur\_name}\K({*}\\{an\_output\_file});{}$\6
${}\\{cur\_repl}\K{}$(\&{text\_pointer}) \\{cur\_name}${}\MG\\{equiv};{}$\6
${}\\{cur\_byte}\K\\{cur\_repl}\MG\\{tok\_start};{}$\6
\\{set\_cur\_end}(\,);\6
\&{while} ${}(\\{stack\_ptr}>\\{stack}){}$\1\5
\\{get\_output}(\,);\2\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\par
\Q166.
\U48.\fi

\M{56}If a \.{@h} was not encountered in the input,
we go through the list of replacement texts and copy the ones
that refer to macros, preceded by the \.{\#define} preprocessor command.

\Y\B\4\X56:Output macro definitions if appropriate\X${}\E{}$\6
\&{if} ${}(\R\\{output\_defs\_seen}){}$\1\5
\\{output\_defs}(\,);\2\par
\U48.\fi

\M{57}%modified
In shared and export files there will be a comment along with the macro
definitions that gives us the section number the macro was defined in.
This is required by \.{mCWEAVE}. Since we do not want to output the comment
every time we output a definition, we keep track of the last section number
we have written to our shared and export files in
\PB{\\{exp\_last\_def\_section\_comment}} and \PB{\\{shr\_last\_def\_section%
\_comment}},
respectively.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{boolean} \\{output\_defs\_seen}${}\K\T{0};{}$\6
\&{int} \\{exp\_last\_def\_section\_comment};\6
\&{int} \\{shr\_last\_def\_section\_comment};\par
\fi

\M{58}%mine
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{output\_defs\_seen}\K\T{0};{}$\6
${}\\{exp\_last\_def\_section\_comment}\K\T{0}{}$;\C{ no comment with section
number written so far }\6
${}\\{shr\_last\_def\_section\_comment}\K\T{0}{}$;\par
\fi

\M{59}\B\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{output\_defs}(\,);\par
\fi

\M{60}%modified
The definitions may be preceded by a comment containing the section number
where they have been defined.
After this comment, we may find some export keywords
which indicate where to export the macro.

When we output the macro definitions we also append the \PB{$\#$ \&{include}}
statements for the export files.
\Y\B\&{void} \\{output\_defs}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{sixteen\_bits} \\{where}${},{}$ \|a;\6
\&{int} \\{line\_no};\6
\&{eight\_bits} ${}{*}\\{cp};{}$\6
\&{char} \\{comment}[\T{20}]${},{}$ ${}{*}\\{com};{}$\7
\X68:Output a constant with the same name as \PB{\\{C\_file\_name}}\X;\6
${}\\{push\_level}(\NULL);{}$\6
\&{for} ${}(\\{cur\_text}\K\\{text\_info}+\T{1};{}$ ${}\\{cur\_text}<\\{text%
\_ptr};{}$ ${}\\{cur\_text}\PP){}$\1\6
\&{if} ${}(\\{cur\_text}\MG\\{text\_link}\E\T{0}){}$\5
${}\{{}$\C{ \PB{\\{cur\_text}} is the text for a macro }\1\6
${}\\{cp}\K\\{cur\_text}\MG\\{tok\_start};{}$\6
${}{*}\\{comment}\K\T{0};{}$\6
\&{if} ${}(\R\\{strncmp}(\\{cp},\39\.{"\\03/*"},\39\T{3})){}$\5
${}\{{}$\C{ introduced by comment containing section number }\1\6
${}\\{com}\K\\{comment};{}$\6
\&{while} ${}({*}\PP\\{cp}\I\\{constant}){}$\1\5
${}{*}\\{com}\PP\K{*}\\{cp};{}$\2\6
${}{*}\\{com}\K\T{0};{}$\6
${}\PP\\{cp};{}$\6
\4${}\}{}$\2\6
${}\\{where}\K\T{0}{}$;\C{ where to output the definitions }\6
\&{while} ${}({*}\\{cp}\E\\{special\_command}){}$\5
${}\{{}$\C{ this macro was preceded by an export command }\1\6
\&{if} ${}({*}\PP\\{cp}\G\T{\~200}){}$\5
${}\{{}$\1\6
${}\|a\K(({*}\\{cp}-\T{\~200})\LL\T{8})+\\{cp}[\T{1}];{}$\6
\&{switch} (\|a)\5
${}\{{}$\1\6
\4\&{case} \\{id\_global}:\5
${}\\{where}\MRL{{\OR}{\K}}\\{exp\_global};{}$\6
\&{break};\6
\4\&{case} \\{id\_export}:\5
${}\\{where}\MRL{{\OR}{\K}}\\{exp\_export};{}$\6
\&{break};\6
\4\&{case} \\{id\_shared}:\5
${}\\{where}\MRL{{\OR}{\K}}\\{exp\_shared};{}$\6
\&{break};\6
\4${}\}{}$\2\6
${}\\{cp}\MRL{+{\K}}\T{2}{}$;\C{ skip export command }\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{where}\AND\\{exp\_export}){}$\5
${}\{{}$\1\6
\X61:Write definitions to export file\X;\6
\4${}\}{}$\2\6
\&{if} ${}(\\{where}\AND\\{exp\_shared}){}$\5
${}\{{}$\1\6
\X62:Write definitions to shared file\X;\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{C\_file}\K\\{Code\_file}{}$;\C{ write to ordinary \CEE/ file }\6
\\{write\_def}(\\{cp});\6
\4${}\}{}$\2\6
${}\\{C\_file}\K\\{Code\_file};{}$\6
\4${}\}{}$\2\2\6
\X174:Output direct import \PB{$\#$ \&{include}}s\X;\6
\X63:Output include for own shared\X;\6
\X70:Output global stuff and all variables\X;\6
\4${}\}{}$\2\par
\fi

\M{61}If we saw an \&{export} command after the optional comment,
we have to write it to the \PB{\\{Exp\_file}}. If there is a comment and if
the section number contained in it is not the same as the last one written
to the export file, we also output the comment.
\Y\B\4\X61:Write definitions to export file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{line\_no}\K\\{cur\_line}{}$;\C{ don't count lines, we will write it again
(\CEE/ or shared file) }\6
${}\\{C\_file}\K\\{Exp\_file};{}$\6
\&{if} ${}({*}\\{comment}){}$\5
${}\{{}$\C{ also write comment, if different from last one written }\1\6
\&{int} \\{sec\_no};\7
${}\\{sscanf}(\\{comment}+\T{10},\39\.{"\%d"},\39{\AND}\\{sec\_no});{}$\6
\&{if} ${}(\\{sec\_no}>\\{exp\_last\_def\_section\_comment}){}$\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\%s"},\39\\{comment});{}$\6
\\{flush\_buffer}(\,);\6
${}\\{exp\_last\_def\_section\_comment}\K\\{sec\_no};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\\{write\_def}(\\{cp});\C{ write definition to export file }\6
${}\\{cur\_line}\K\\{line\_no};{}$\6
\4${}\}{}$\2\par
\U60.\fi

\M{62}
\Y\B\4\X62:Write definitions to shared file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{C\_file}\K\\{Shr\_file};{}$\6
\&{if} ${}({*}\\{comment}){}$\5
${}\{{}$\1\6
\&{int} \\{sec\_no};\7
${}\\{sscanf}(\\{comment}+\T{10},\39\.{"\%d"},\39{\AND}\\{sec\_no});{}$\6
\&{if} ${}(\\{sec\_no}>\\{shr\_last\_def\_section\_comment}){}$\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\%s"},\39\\{comment});{}$\6
\\{flush\_buffer}(\,);\6
${}\\{shr\_last\_def\_section\_comment}\K\\{sec\_no};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\\{write\_def}(\\{cp});\C{ write it to shared file }\6
\4${}\}{}$\2\par
\U60.\fi

\M{63}%mine
Every chapter automatically knows about its own shared stuff, so
we have to include our chapter's own shared file.
\Y\B\4\X63:Output include for own shared\X${}\E{}$\6
${}\{{}$\1\6
\&{char} \\{expname}[\\{max\_file\_name\_length}];\6
\&{char} ${}{*}\\{dot};{}$\7
\&{if} ${}(\\{used\_exports}\AND\\{exp\_shared}){}$\5
${}\{{}$\1\6
${}\\{strcpy}(\\{expname},\39\\{Shr\_file\_name});{}$\6
${}\\{dot}\K\\{file\_name\_ext}(\\{expname});{}$\6
\&{if} (\\{dot})\1\5
${}{*}\\{dot}\K\T{0};{}$\2\6
${}\\{strcat}(\\{expname},\39\.{".shr"});{}$\6
${}\\{C\_printf}(\.{"\#include\ \\"\%s\\""},\39\\{expname});{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\6
\\{pop\_level}(\T{0});\6
\4${}\}{}$\2\par
\U60.\fi

\M{64}\B\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{write\_def}(\,);\par
\fi

\M{65}%moved
Write the definition starting at \PB{\\{tok}} to \PB{\\{C\_file}}.
\Y\B\&{void} \\{write\_def}(\\{tok})\1\1\6
\&{eight\_bits} ${}{*}\\{tok};\2\2{}$\6
${}\{{}$\1\6
\&{sixteen\_bits} \|a;\7
${}\\{cur\_byte}\K\\{tok};{}$\6
${}\\{cur\_end}\K(\\{cur\_text}+\T{1})\MG\\{tok\_start};{}$\6
${}\\{C\_printf}(\.{"\%s"},\39\.{"\#define\ "});{}$\6
${}\\{out\_state}\K\\{normal};{}$\6
${}\\{protect}\K\T{1}{}$;\C{ newlines should be preceded by \PB{\.{'\\\\'}} }\6
\&{while} ${}(\\{cur\_byte}<\\{cur\_end}){}$\5
${}\{{}$\1\6
${}\|a\K{*}\\{cur\_byte}\PP;{}$\6
\&{if} ${}(\\{cur\_byte}\E\\{cur\_end}\W\|a\E\.{'\\n'}){}$\1\5
\&{break};\C{ disregard a final newline }\2\6
\&{if} ${}(\\{out\_state}\E\\{verbatim}\W\|a\I\\{string}\W\|a\I\\{constant}\W%
\|a\I\.{'\\n'}){}$\1\5
\\{C\_putc}(\|a);\C{ a high-bit character can occur in a string }\2\6
\&{else} \&{if} ${}(\|a<\T{\~200}){}$\1\5
\\{out\_char}(\|a);\C{ one-byte token }\2\6
\&{else}\5
${}\{{}$\1\6
${}\|a\K(\|a-\T{\~200})*\T{\~400}+{*}\\{cur\_byte}\PP;{}$\6
\&{if} ${}(\|a<\T{\~24000}){}$\5
${}\{{}$\C{ \PB{$\T{\~24000}\E(\T{\~250}-\T{\~200})*\T{\~400}$} }\1\6
${}\\{cur\_val}\K\|a;{}$\6
\\{out\_char}(\\{identifier});\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\|a<\T{\~50000}){}$\5
${}\{{}$\1\6
\\{confusion}(\.{"macro\ defs\ have\ str}\)\.{ange\ char"});\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{cur\_val}\K\|a-\T{\~50000};{}$\6
${}\\{cur\_section}\K\\{cur\_val};{}$\6
\\{out\_char}(\\{section\_number});\6
\4${}\}{}$\C{ no other cases }\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{protect}\K\T{0};{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\par
\fi

\M{66}
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} \\{file\_name\_constant}[\\{max\_file\_name\_length}];\6
\&{sixteen\_bits} \\{id\_file\_name\_constant};\par
\fi

\M{67}Since we don't want to have the compiler read our export files
more than once, we protect our files with preprocessor constants.
There is a constant defined at the beginning of each
export file which gets set when the file is read by the compiler and
is checked at the very beginning.\smallskip

\8\#\&{ifndef} \.{FILE\_NAME}\6
\8\#\&{define} \.{FILE\_NAME}\6
\hbox{\dots}\6
\8\#\&{endif}\par
\smallskip\noindent
In order to do so, we have to convert the \PB{\\{C\_file\_name}} into a
constant
\PB{\\{file\_name\_constant}} with no special characters.
\Y\B\4\X67:Create file name constant\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp},{}$ ${}{*}\\{fn};{}$\7
${}\\{cp}\K\\{C\_file\_name}{}$;\C{ create a valid constant of the filename }\6
${}\\{fn}\K\\{file\_name\_constant};{}$\6
\&{do}\5
${}\{{}$\1\6
\&{if} ${}(\\{isalnum}({*}\\{cp})){}$\1\5
${}{*}\\{fn}\K{*}\\{cp};{}$\2\6
\&{else}\1\5
${}{*}\\{fn}\K\.{'\_'}{}$;\C{ nonalpha characters become \.{\UL} }\2\6
${}\\{cp}\PP;{}$\6
${}\\{fn}\PP;{}$\6
\4${}\}{}$\2\5
\&{while} ${}({*}\\{cp});{}$\6
${}{*}\\{fn}\K\.{'\\0'};{}$\6
${}\\{id\_file\_name\_constant}\K\\{id\_lookup}(\\{file\_name\_constant},\39%
\\{fn},\39\T{0})-\\{name\_dir};{}$\6
\4${}\}{}$\2\par
\U5.\fi

\M{68}
\Y\B\4\X68:Output a constant with the same name as \PB{\\{C\_file\_name}}\X${}%
\E{}$\6
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\#define\ \%s"},\39\\{file\_name\_constant});{}$\6
\\{flush\_buffer}(\,);\C{ define constant }\6
\4${}\}{}$\2\par
\U60.\fi

\M{69}\B\X8:Include files\X${}\mathrel+\E{}$\6
\8\#\&{include} \.{<stddef.h>}\par
\fi

\M{70}%mine
As we will see in the section about export commands, we have a lot of
information that goes to the \CEE/ file. This includes variables,
\&{global} datatypes and \&{global} declarations.

\PB{\\{push\_export\_section}} outputs this information which was gathered
during pass one. Since this is a stack, the topmost section will
appear first in the file.
We will talk about export sections in more detail when we will be
treating export commands.
\Y\B\4\X70:Output global stuff and all variables\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|i;\7
${}\\{push\_export\_section}({\AND}\\{var\_sec});{}$\6
${}\\{var\_sec}.\\{first\_text}\K\\{var\_sec}.\\{last\_text}\K\NULL{}$;\C{ only
output variables once }\6
\&{for} ${}(\|i\K\\{num\_export\_sections}-\T{1};{}$ ${}\|i\G\T{0};{}$ ${}\|i%
\MM){}$\1\5
${}\\{push\_export\_section}({\AND}\\{glb\_sec}[\|i]);{}$\2\6
\4${}\}{}$\2\par
\U60.\fi

\M{71}A many-way switch is used to send the output.  Note that this function
is not called if \PB{$\\{out\_state}\E\\{verbatim}$}, except perhaps with
arguments
\PB{\.{'\\n'}} (protect the newline), \PB{\\{string}} (end the string), or \PB{%
\\{constant}}
(end the constant).

\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{out\_char}(\,);\par
\fi

\M{72}%modified
\Y\B\&{static} \&{void} \\{out\_char}(\\{cur\_char})\1\1\6
\&{eight\_bits} \\{cur\_char};\2\2\6
${}\{{}$\1\6
\&{char} ${}{*}\|j,{}$ ${}{*}\|k{}$;\C{ pointer into \PB{\\{byte\_mem}} }\7
\4\\{restart}:\6
\&{switch} (\\{cur\_char})\5
${}\{{}$\1\6
\4\&{case} \.{'\\n'}:\6
\&{if} (\\{protect})\1\5
\\{C\_putc}(\.{'\ '});\2\6
\&{if} ${}(\\{protect}\V\\{out\_state}\E\\{verbatim}){}$\1\5
\\{C\_putc}(\.{'\\\\'});\2\6
\\{flush\_buffer}(\,);\6
\&{if} ${}(\\{out\_state}\I\\{verbatim}){}$\1\5
${}\\{out\_state}\K\\{normal};{}$\2\6
\&{break};\6
\hbox{\4}\X76:Case of an identifier\X;\6
\hbox{\4}\X77:Case of a section number\X;\6
\hbox{\4}\X73:Cases like \.{!=}\X;\6
\4\&{case} \.{'='}:\5
\\{C\_putc}(\.{'='});\6
\\{C\_putc}(\.{'\ '});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{join}:\5
${}\\{out\_state}\K\\{unbreakable};{}$\6
\&{break};\6
\4\&{case} \\{constant}:\6
\&{if} ${}(\\{out\_state}\E\\{verbatim}){}$\5
${}\{{}$\1\6
${}\\{out\_state}\K\\{num\_or\_id};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{out\_state}\E\\{num\_or\_id}){}$\1\5
\\{C\_putc}(\.{'\ '});\2\6
${}\\{out\_state}\K\\{verbatim};{}$\6
\&{break};\6
\4\&{case} \\{string}:\6
\&{if} ${}(\\{out\_state}\E\\{verbatim}){}$\1\5
${}\\{out\_state}\K\\{normal};{}$\2\6
\&{else}\1\5
${}\\{out\_state}\K\\{verbatim};{}$\2\6
\&{break};\6
\4\&{case} \\{ignore}:\5
\&{break};\6
\4\&{case} \.{'/'}:\5
\\{C\_putc}(\.{'/'});\6
${}\\{out\_state}\K\\{post\_slash};{}$\6
\&{break};\6
\4\&{case} \.{'*'}:\6
\&{if} ${}(\\{out\_state}\E\\{post\_slash}){}$\1\5
\\{C\_putc}(\.{'\ '});\C{ fall through }\2\6
\4\&{default}:\5
\\{C\_putc}(\\{cur\_char});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{73}\B\X73:Cases like \.{!=}\X${}\E{}$\6
\4\&{case} \\{plus\_plus}:\5
\\{C\_putc}(\.{'+'});\6
\\{C\_putc}(\.{'+'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{minus\_minus}:\5
\\{C\_putc}(\.{'-'});\6
\\{C\_putc}(\.{'-'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{minus\_gt}:\5
\\{C\_putc}(\.{'-'});\6
\\{C\_putc}(\.{'>'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{gt\_gt}:\5
\\{C\_putc}(\.{'>'});\6
\\{C\_putc}(\.{'>'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{eq\_eq}:\5
\\{C\_putc}(\.{'='});\6
\\{C\_putc}(\.{'='});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{lt\_lt}:\5
\\{C\_putc}(\.{'<'});\6
\\{C\_putc}(\.{'<'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{gt\_eq}:\5
\\{C\_putc}(\.{'>'});\6
\\{C\_putc}(\.{'='});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{lt\_eq}:\5
\\{C\_putc}(\.{'<'});\6
\\{C\_putc}(\.{'='});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{not\_eq}:\5
\\{C\_putc}(\.{'!'});\6
\\{C\_putc}(\.{'='});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{and\_and}:\5
\\{C\_putc}(\.{'\&'});\6
\\{C\_putc}(\.{'\&'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{or\_or}:\5
\\{C\_putc}(\.{'|'});\6
\\{C\_putc}(\.{'|'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{dot\_dot\_dot}:\5
\\{C\_putc}(\.{'.'});\6
\\{C\_putc}(\.{'.'});\6
\\{C\_putc}(\.{'.'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{colon\_colon}:\5
\\{C\_putc}(\.{':'});\6
\\{C\_putc}(\.{':'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{period\_ast}:\5
\\{C\_putc}(\.{'.'});\6
\\{C\_putc}(\.{'*'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\6
\4\&{case} \\{minus\_gt\_ast}:\5
\\{C\_putc}(\.{'-'});\6
\\{C\_putc}(\.{'>'});\6
\\{C\_putc}(\.{'*'});\6
${}\\{out\_state}\K\\{normal};{}$\6
\&{break};\par
\U72.\fi

\M{74}When an identifier is output to the \CEE/ file, characters in the
range 128--255 must be changed into something else, so the \CEE/
compiler won't complain.  By default, \.{CTANGLE} converts the
character with code $16 x+y$ to the three characters `\.X$xy$', but
a different transliteration table can be specified.  Thus a German
might want {\it gr\"un\/} to appear as a still readable \.{gruen}.
This makes debugging a lot less confusing.

\Y\B\4\D$\\{translit\_length}$ \5
\T{10}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} \\{translit}[\T{128}][\\{translit\_length}];\par
\fi

\M{75}\B\X20:Set initial values\X${}\mathrel+\E{}$\6
${}\{{}$\1\6
\&{int} \|i;\7
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\T{128};{}$ ${}\|i\PP){}$\1\5
${}\\{sprintf}(\\{translit}[\|i],\39\.{"X\%02X"},\39{}$(\&{unsigned}) ${}(%
\T{128}+\|i));{}$\2\6
\4${}\}{}$\2\par
\fi

\M{76}\B\X76:Case of an identifier\X${}\E{}$\6
\4\&{case} \\{identifier}:\6
\&{if} ${}(\\{out\_state}\E\\{num\_or\_id}){}$\1\5
\\{C\_putc}(\.{'\ '});\2\6
${}\|j\K(\\{cur\_val}+\\{name\_dir})\MG\\{byte\_start};{}$\6
${}\|k\K(\\{cur\_val}+\\{name\_dir}+\T{1})\MG\\{byte\_start};{}$\6
\&{while} ${}(\|j<\|k){}$\5
${}\{{}$\1\6
\&{if} ((\&{unsigned} \&{char}) ${}({*}\|j)<\T{\~200}){}$\1\5
${}\\{C\_putc}({*}\|j);{}$\2\6
\&{else}\1\5
${}\\{C\_printf}(\.{"\%s"},\39{}$\\{translit}[(\&{unsigned} \&{char}) ${}({*}%
\|j)-\T{\~200}]);{}$\2\6
${}\|j\PP;{}$\6
\4${}\}{}$\2\6
${}\\{out\_state}\K\\{num\_or\_id};{}$\6
\&{break};\par
\U72.\fi

\M{77}\B\X77:Case of a section number\X${}\E{}$\6
\4\&{case} \\{section\_number}:\6
\&{if} ${}(\\{cur\_val}>\T{0}){}$\1\5
${}\\{C\_printf}(\.{"/*\%d:*/"},\39\\{cur\_val});{}$\2\6
\&{else} \&{if} ${}(\\{cur\_val}<\T{0}){}$\1\5
${}\\{C\_printf}(\.{"/*:\%d*/"},\39{-}\\{cur\_val});{}$\2\6
\&{else} \&{if} (\\{protect})\5
${}\{{}$\1\6
${}\\{cur\_byte}\MRL{+{\K}}\T{4}{}$;\C{ skip line number and file name }\6
${}\\{cur\_char}\K\.{'\\n'};{}$\6
\&{goto} \\{restart};\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{sixteen\_bits} \|a;\7
${}\|a\K\T{\~400}*{*}\\{cur\_byte}\PP;{}$\6
${}\|a\MRL{+{\K}}{*}\\{cur\_byte}\PP{}$;\C{ gets the line number }\6
${}\\{C\_printf}(\.{"\\n\#line\ \%d\ \\""},\39\|a);{}$\6
${}\\{cur\_val}\K{*}\\{cur\_byte}\PP;{}$\6
${}\\{cur\_val}\K\T{\~400}*(\\{cur\_val}-\T{\~200})+{*}\\{cur\_byte}\PP{}$;\C{
points to the file name }\6
\&{for} ${}(\|j\K(\\{cur\_val}+\\{name\_dir})\MG\\{byte\_start},\39\|k\K(\\{cur%
\_val}+\\{name\_dir}+\T{1})\MG\\{byte\_start};{}$ ${}\|j<\|k;{}$ ${}\|j\PP){}$%
\1\5
${}\\{C\_putc}({*}\|j);{}$\2\6
${}\\{C\_printf}(\.{"\%s"},\39\.{"\\"\\n"});{}$\6
\4${}\}{}$\2\6
\&{break};\par
\U72.\fi

\N{0}{78}Introduction to the input phase.
We have now seen that \.{CTANGLE} will be able to output the full
\CEE/ program, if we can only get that program into the byte memory in
the proper format. The input process is something like the output process
in reverse, since we compress the text as we read it in and we expand it
as we write it out.

There are three main input routines. The most interesting is the one that gets
the next token of a \CEE/ text; the other two are used to scan rapidly past
\TEX/ text in the \.{CWEB} source code. One of the latter routines will jump to
the next token that starts with `\.{@}', and the other skips to the end
of a \CEE/ comment.

\fi

\M{79}Control codes in \.{CWEB} begin with `\.{@}', and the next character
identifies the code. Some of these are of interest only to \.{CWEAVE},
so \.{CTANGLE} ignores them; the others are converted by \.{CTANGLE} into
internal code numbers by the \PB{\\{ccode}} table below. The ordering
of these internal code numbers has been chosen to simplify the program logic;
larger numbers are given to the control codes that denote more significant
milestones.

\Y\B\4\D$\\{ignore}$ \5
\T{0}\C{ control code of no interest to \.{CTANGLE} }\par
\B\4\D$\\{special\_command}$ \5
\T{\~301}\C{ control code for special commands introduces by '\.{@$\_$}' }\par
\B\4\D$\\{ord}$ \5
\T{\~302}\C{ control code for `\.{@'}' }\par
\B\4\D$\\{control\_text}$ \5
\T{\~303}\C{ control code for `\.{@t}', `\.{@\^}', etc. }\par
\B\4\D$\\{translit\_code}$ \5
\T{\~304}\C{ control code for `\.{@l}' }\par
\B\4\D$\\{output\_defs\_code}$ \5
\T{\~305}\C{ control code for `\.{@h}' }\par
\B\4\D$\\{format\_code}$ \5
\T{\~306}\C{ control code for `\.{@f}' }\par
\B\4\D$\\{definition}$ \5
\T{\~307}\C{ control code for `\.{@d}' }\par
\B\4\D$\\{begin\_C}$ \5
\T{\~310}\C{ control code for `\.{@c}' }\par
\B\4\D$\\{section\_name}$ \5
\T{\~311}\C{ control code for `\.{@<}' }\par
\B\4\D$\\{new\_section}$ \5
\T{\~312}\C{ control code for `\.{@\ }' and `\.{@*}' }\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{eight\_bits} \\{ccode}[\T{256}];\C{ meaning of a char following \.{@} }\par
\fi

\M{80}\B\X20:Set initial values\X${}\mathrel+\E{}$\6
${}\{{}$\1\6
\&{int} \|c;\C{ must be \PB{\&{int}} so the \PB{\&{for}} loop will end }\7
\&{for} ${}(\|c\K\T{0};{}$ ${}\|c<\T{256};{}$ ${}\|c\PP){}$\1\5
${}\\{ccode}[\|c]\K\\{ignore};{}$\2\6
${}\\{ccode}[\.{'\ '}]\K\\{ccode}[\.{'\\t'}]\K\\{ccode}[\.{'\\n'}]\K\\{ccode}[%
\.{'\\v'}]\K\\{ccode}[\.{'\\r'}]\K\\{ccode}[\.{'\\f'}]\K\\{ccode}[\.{'*'}]\K%
\\{new\_section};{}$\6
${}\\{ccode}[\.{'@'}]\K\.{'@'};{}$\6
${}\\{ccode}[\.{'='}]\K\\{string};{}$\6
${}\\{ccode}[\.{'d'}]\K\\{ccode}[\.{'D'}]\K\\{definition};{}$\6
${}\\{ccode}[\.{'f'}]\K\\{ccode}[\.{'F'}]\K\\{ccode}[\.{'s'}]\K\\{ccode}[%
\.{'S'}]\K\\{format\_code};{}$\6
${}\\{ccode}[\.{'c'}]\K\\{ccode}[\.{'C'}]\K\\{ccode}[\.{'p'}]\K\\{ccode}[%
\.{'P'}]\K\\{begin\_C};{}$\6
${}\\{ccode}[\.{'\^'}]\K\\{ccode}[\.{':'}]\K\\{ccode}[\.{'.'}]\K\\{ccode}[%
\.{'t'}]\K\\{ccode}[\.{'T'}]\K\\{ccode}[\.{'q'}]\K\\{ccode}[\.{'Q'}]\K%
\\{control\_text};{}$\6
${}\\{ccode}[\.{'h'}]\K\\{ccode}[\.{'H'}]\K\\{output\_defs\_code};{}$\6
${}\\{ccode}[\.{'l'}]\K\\{ccode}[\.{'L'}]\K\\{translit\_code};{}$\6
${}\\{ccode}[\.{'\&'}]\K\\{join};{}$\6
${}\\{ccode}[\.{'<'}]\K\\{ccode}[\.{'('}]\K\\{section\_name};{}$\6
${}\\{ccode}[\.{'\\''}]\K\\{ord};{}$\6
${}\\{ccode}[\.{'\_'}]\K\\{special\_command};{}$\6
\4${}\}{}$\2\par
\fi

\M{81}The \PB{\\{skip\_ahead}} procedure reads through the input at fairly high
speed
until finding the next non-ignorable control code, which it returns.

\Y\B\&{eight\_bits} \\{skip\_ahead}(\,)\C{ skip to next control code }\6
${}\{{}$\1\6
\&{eight\_bits} \|c;\C{ control code found }\7
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}>\\{limit}\W(\\{get\_line}(\,)\E\T{0})){}$\1\5
\&{return} (\\{new\_section});\2\6
${}{*}(\\{limit}+\T{1})\K\.{'@'};{}$\6
\&{while} ${}({*}\\{loc}\I\.{'@'}){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{if} ${}(\\{loc}\Z\\{limit}){}$\5
${}\{{}$\1\6
${}\\{loc}\PP;{}$\6
${}\|c\K\\{ccode}{}$[(\&{eight\_bits}) ${}{*}\\{loc}];{}$\6
${}\\{loc}\PP;{}$\6
\&{if} ${}(\|c\I\\{ignore}\V{*}(\\{loc}-\T{1})\E\.{'>'}){}$\1\5
\&{return} (\|c);\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{82}The \PB{\\{skip\_comment}} procedure reads through the input at somewhat
high
speed in order to pass over comments, which \.{CTANGLE} does not transmit
to the output. If the comment is introduced by \.{/*}, \PB{\\{skip\_comment}}
proceeds until finding the end-comment token \.{*/} or a newline; in the
latter case \PB{\\{skip\_comment}} will be called again by \PB{\\{get\_next}},
since the
comment is not finished.  This is done so that the each newline in the
\CEE/ part of a section is copied to the output; otherwise the \&{\#line}
commands inserted into the \CEE/ file by the output routines become useless.
On the other hand, if the comment is introduced by \.{//} (i.e., if it
is a \CPLUSPLUS/ ``short comment''), it always is simply delimited by the next
newline. The boolean argument \PB{\\{is\_long\_comment}} distinguishes between
the two types of comments.

If \PB{\\{skip\_comment}} comes to the end of the section, it prints an error
message.
No comment, long or short, is allowed to contain `\.{@\ }' or `\.{@*}'.

\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{boolean} \\{comment\_continues}${}\K\T{0}{}$;\C{ are we scanning a comment?
}\par
\fi

\M{83}%mine
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{comment\_continues}\K\T{0}{}$;\par
\fi

\M{84}\B\&{int} \\{skip\_comment}(\\{is\_long\_comment})\C{ skips over comments
}\1\1\6
\&{boolean} \\{is\_long\_comment};\2\2\6
${}\{{}$\1\6
\&{char} \|c;\C{ current character }\7
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}>\\{limit}){}$\5
${}\{{}$\1\6
\&{if} (\\{is\_long\_comment})\5
${}\{{}$\1\6
\&{if} (\\{get\_line}(\,))\1\5
\&{return} ${}(\\{comment\_continues}\K\T{1});{}$\2\6
\&{else}\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Input\ ended\ in\ mi}\)\.{d-comment"});\6
\&{return} ${}(\\{comment\_continues}\K\T{0});{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\&{return} ${}(\\{comment\_continues}\K\T{0});{}$\2\6
\4${}\}{}$\2\6
${}\|c\K{*}(\\{loc}\PP);{}$\6
\&{if} ${}(\\{is\_long\_comment}\W\|c\E\.{'*'}\W{*}\\{loc}\E\.{'/'}){}$\5
${}\{{}$\1\6
${}\\{loc}\PP;{}$\6
\&{return} ${}(\\{comment\_continues}\K\T{0});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\|c\E\.{'@'}){}$\5
${}\{{}$\1\6
\&{if} (\\{ccode}[(\&{eight\_bits}) ${}{*}\\{loc}]\E\\{new\_section}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Section\ name\ ende}\)\.{d\ in\ mid-comment"});\6
${}\\{loc}\MM;{}$\6
\&{return} ${}(\\{comment\_continues}\K\T{0});{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{loc}\PP;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\N{1}{85}Inputting the next token.

\Y\B\4\D$\\{constant}$ \5
\T{\~3}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{name\_pointer} \\{cur\_section\_name};\C{ name of section just scanned }\6
\&{int} \\{no\_where};\C{ suppress \PB{\\{print\_where}}? }\par
\fi

\M{86}\B\X8:Include files\X${}\mathrel+\E{}$\6
\8\#\&{include} \.{<ctype.h>}\C{ definition of \PB{\\{isalpha}}, \PB{%
\\{isdigit}} and so on }\6
\8\#\&{include} \.{<stdlib.h>}\C{ definition of \PB{\\{exit}} }\par
\fi

\M{87}As one might expect, \PB{\\{get\_next}} consists mostly of a big switch
that branches to the various special cases that can arise.

\Y\B\4\D$\\{isxalpha}(\|c)$ \5
$((\|c)\E\.{'\_'}{}$)\C{ non-alpha character allowed in identifier }\par
\B\4\D$\\{ishigh}(\|c)$ \5
((\&{unsigned} \&{char}) (\|c)${}>\T{\~177}{}$)\par
\Y\B\&{eight\_bits} \\{get\_next}(\,)\C{ produces the next input token }\6
${}\{{}$\1\6
\&{static} \&{int} \\{preprocessing}${}\K\T{0};{}$\6
\&{eight\_bits} \|c;\C{ the current character }\7
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}>\\{limit}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{preprocessing}\W{*}(\\{limit}-\T{1})\I\.{'\\\\'}){}$\1\5
${}\\{preprocessing}\K\T{0};{}$\2\6
\&{if} ${}(\\{get\_line}(\,)\E\T{0}){}$\1\5
\&{return} (\\{new\_section});\2\6
\&{else} \&{if} ${}(\\{print\_where}\W\R\\{no\_where}){}$\5
${}\{{}$\1\6
${}\\{print\_where}\K\T{0};{}$\6
\X101:Insert the line number into \PB{\\{tok\_mem}}\X;\6
\4${}\}{}$\2\6
\&{else}\1\5
\&{return} (\.{'\\n'});\2\6
\4${}\}{}$\2\6
${}\|c\K{*}\\{loc};{}$\6
\&{if} ${}(\\{comment\_continues}\V(\|c\E\.{'/'}\W({*}(\\{loc}+\T{1})\E\.{'*'}%
\V{*}(\\{loc}+\T{1})\E\.{'/'}))){}$\5
${}\{{}$\1\6
${}\\{skip\_comment}(\\{comment\_continues}\V{*}(\\{loc}+\T{1})\E\.{'*'}){}$;%
\C{ scan to end of comment or newline }\6
\&{if} (\\{comment\_continues})\1\5
\&{return} (\.{'\\n'});\2\6
\&{else}\1\5
\&{continue};\2\6
\4${}\}{}$\2\6
${}\\{loc}\PP;{}$\6
\&{if} ${}(\\{xisdigit}(\|c)\V\|c\E\.{'\\\\'}\V\|c\E\.{'.'}){}$\1\5
\X90:Get a constant\X\2\6
\&{else} \&{if} ${}(\|c\E\.{'\\''}\V\|c\E\.{'"'}\V(\|c\E\.{'L'}\W({*}\\{loc}\E%
\.{'\\''}\V{*}\\{loc}\E\.{'"'}))){}$\1\5
\X91:Get a string\X\2\6
\&{else} \&{if} ${}(\\{isalpha}(\|c)\V\\{isxalpha}(\|c)\V\\{ishigh}(\|c)){}$\1\5
\X89:Get an identifier\X\2\6
\&{else} \&{if} ${}(\|c\E\.{'@'}){}$\1\5
\X92:Get control code and possible section name\X\2\6
\&{else} \&{if} (\\{xisspace}(\|c))\5
${}\{{}$\1\6
\&{if} ${}(\R\\{preprocessing}\V\\{loc}>\\{limit}){}$\1\5
\&{continue};\C{ we don't want a blank after a final backslash }\2\6
\&{else}\1\5
\&{return} (\.{'\ '});\C{ ignore spaces and tabs, unless preprocessing }\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\|c\E\.{'\#'}\W\\{loc}\E\\{buffer}+\T{1}){}$\1\5
${}\\{preprocessing}\K\T{1};{}$\2\6
\4\\{mistake}:\5
\X88:Compress two-symbol operator\X\6
\&{return} (\|c);\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{88}The following code assigns values to the combinations \.{++},
\.{--}, \.{->}, \.{>=}, \.{<=}, \.{==}, \.{<<}, \.{>>}, \.{!=}, \.{\PB{}} and
\.{\&\&}, and to the \CPLUSPLUS/
combinations \.{...}, \.{::}, \.{.*} and \.{->*}.
The compound assignment operators (e.g., \.{+=}) are
treated as separate tokens.

\Y\B\4\D$\\{compress}(\|c)$ \5
\&{if} ${}(\\{loc}\PP\Z\\{limit})$ \&{return} (\|c)\par
\Y\B\4\X88:Compress two-symbol operator\X${}\E{}$\6
\&{switch} (\|c)\5
${}\{{}$\1\6
\4\&{case} \.{'+'}:\6
\&{if} ${}({*}\\{loc}\E\.{'+'}){}$\1\5
\\{compress}(\\{plus\_plus});\2\6
\&{break};\6
\4\&{case} \.{'-'}:\6
\&{if} ${}({*}\\{loc}\E\.{'-'}){}$\5
${}\{{}$\1\6
\\{compress}(\\{minus\_minus});\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{loc}\E\.{'>'}){}$\1\6
\&{if} ${}({*}(\\{loc}+\T{1})\E\.{'*'}){}$\5
${}\{{}$\1\6
${}\\{loc}\PP;{}$\6
\\{compress}(\\{minus\_gt\_ast});\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{compress}(\\{minus\_gt});\2\2\6
\&{break};\6
\4\&{case} \.{'.'}:\6
\&{if} ${}({*}\\{loc}\E\.{'*'}){}$\5
${}\{{}$\1\6
\\{compress}(\\{period\_ast});\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{loc}\E\.{'.'}\W{*}(\\{loc}+\T{1})\E\.{'.'}){}$\5
${}\{{}$\1\6
${}\\{loc}\PP;{}$\6
\\{compress}(\\{dot\_dot\_dot});\6
\4${}\}{}$\2\6
\&{break};\6
\4\&{case} \.{':'}:\6
\&{if} ${}({*}\\{loc}\E\.{':'}){}$\1\5
\\{compress}(\\{colon\_colon});\2\6
\&{break};\6
\4\&{case} \.{'='}:\6
\&{if} ${}({*}\\{loc}\E\.{'='}){}$\1\5
\\{compress}(\\{eq\_eq});\2\6
\&{break};\6
\4\&{case} \.{'>'}:\6
\&{if} ${}({*}\\{loc}\E\.{'='}){}$\5
${}\{{}$\1\6
\\{compress}(\\{gt\_eq});\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{loc}\E\.{'>'}){}$\1\5
\\{compress}(\\{gt\_gt});\2\6
\&{break};\6
\4\&{case} \.{'<'}:\6
\&{if} ${}({*}\\{loc}\E\.{'='}){}$\5
${}\{{}$\1\6
\\{compress}(\\{lt\_eq});\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{loc}\E\.{'<'}){}$\1\5
\\{compress}(\\{lt\_lt});\2\6
\&{break};\6
\4\&{case} \.{'\&'}:\6
\&{if} ${}({*}\\{loc}\E\.{'\&'}){}$\1\5
\\{compress}(\\{and\_and});\2\6
\&{break};\6
\4\&{case} \.{'|'}:\6
\&{if} ${}({*}\\{loc}\E\.{'|'}){}$\1\5
\\{compress}(\\{or\_or});\2\6
\&{break};\6
\4\&{case} \.{'!'}:\6
\&{if} ${}({*}\\{loc}\E\.{'='}){}$\1\5
\\{compress}(\\{not\_eq});\2\6
\&{break};\6
\4${}\}{}$\2\par
\U87.\fi

\M{89}\B\X89:Get an identifier\X${}\E{}$\6
${}\{{}$\1\6
${}\\{id\_first}\K\MM\\{loc};{}$\6
\&{while} ${}(\\{isalpha}({*}\PP\\{loc})\V\\{isdigit}({*}\\{loc})\V%
\\{isxalpha}({*}\\{loc})\V\\{ishigh}({*}\\{loc})){}$\1\5
;\2\6
${}\\{id\_loc}\K\\{loc};{}$\6
\&{return} (\\{identifier});\6
\4${}\}{}$\2\par
\U87.\fi

\M{90}\B\X90:Get a constant\X${}\E{}$\6
${}\{{}$\1\6
${}\\{id\_first}\K\\{loc}-\T{1};{}$\6
\&{if} ${}({*}\\{id\_first}\E\.{'.'}\W\R\\{xisdigit}({*}\\{loc})){}$\1\5
\&{goto} \\{mistake};\C{ not a constant }\2\6
\&{if} ${}({*}\\{id\_first}\E\.{'\\\\'}){}$\1\6
\&{while} ${}(\\{xisdigit}({*}\\{loc})){}$\1\5
${}\\{loc}\PP{}$;\C{ octal constant }\2\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}({*}\\{id\_first}\E\.{'0'}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{loc}\E\.{'x'}\V{*}\\{loc}\E\.{'X'}){}$\5
${}\{{}$\C{ hex constant }\1\6
${}\\{loc}\PP;{}$\6
\&{while} ${}(\\{xisxdigit}({*}\\{loc})){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{goto} \\{found};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{while} ${}(\\{xisdigit}({*}\\{loc})){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{if} ${}({*}\\{loc}\E\.{'.'}){}$\5
${}\{{}$\1\6
${}\\{loc}\PP;{}$\6
\&{while} ${}(\\{xisdigit}({*}\\{loc})){}$\1\5
${}\\{loc}\PP;{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}({*}\\{loc}\E\.{'e'}\V{*}\\{loc}\E\.{'E'}){}$\5
${}\{{}$\C{ float constant }\1\6
\&{if} ${}({*}\PP\\{loc}\E\.{'+'}\V{*}\\{loc}\E\.{'-'}){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{while} ${}(\\{xisdigit}({*}\\{loc})){}$\1\5
${}\\{loc}\PP;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4\\{found}:\6
\&{while} ${}({*}\\{loc}\E\.{'u'}\V{*}\\{loc}\E\.{'U'}\V{*}\\{loc}\E\.{'l'}%
\V{*}\\{loc}\E\.{'L'}\V{*}\\{loc}\E\.{'f'}\V{*}\\{loc}\E\.{'F'}){}$\1\5
${}\\{loc}\PP;{}$\2\6
${}\\{id\_loc}\K\\{loc};{}$\6
\&{return} (\\{constant});\6
\4${}\}{}$\2\par
\U87.\fi

\M{91}\CEE/ strings and character constants, delimited by double and single
quotes, respectively, can contain newlines or instances of their own
delimiters if they are protected by a backslash.  We follow this
convention, but do not allow the string to be longer than \PB{\\{longest%
\_name}}.

\Y\B\4\X91:Get a string\X${}\E{}$\6
${}\{{}$\1\6
\&{char} \\{delim}${}\K\|c{}$;\C{ what started the string }\7
${}\\{id\_first}\K\\{section\_text}+\T{1};{}$\6
${}\\{id\_loc}\K\\{section\_text};{}$\6
${}{*}\PP\\{id\_loc}\K\\{delim};{}$\6
\&{if} ${}(\\{delim}\E\.{'L'}){}$\5
${}\{{}$\C{ wide character constant }\1\6
${}\\{delim}\K{*}\\{loc}\PP;{}$\6
${}{*}\PP\\{id\_loc}\K\\{delim};{}$\6
\4${}\}{}$\2\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}\G\\{limit}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}(\\{limit}-\T{1})\I\.{'\\\\'}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ String\ didn't\ end}\)\.{"});\6
${}\\{loc}\K\\{limit};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{get\_line}(\,)\E\T{0}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Input\ ended\ in\ mi}\)\.{ddle\ of\ string"});\6
${}\\{loc}\K\\{buffer};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\PP\\{id\_loc}\Z\\{section\_text\_end}){}$\1\5
${}{*}\\{id\_loc}\K\.{'\\n'}{}$;\C{ will print as       \.{"\\\\\\n"} }\2\6
\4${}\}{}$\2\6
\&{if} ${}((\|c\K{*}\\{loc}\PP)\E\\{delim}){}$\5
${}\{{}$\1\6
\&{if} ${}(\PP\\{id\_loc}\Z\\{section\_text\_end}){}$\1\5
${}{*}\\{id\_loc}\K\|c;{}$\2\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\|c\E\.{'\\\\'}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}\G\\{limit}){}$\1\5
\&{continue};\2\6
\&{if} ${}(\PP\\{id\_loc}\Z\\{section\_text\_end}){}$\1\5
${}{*}\\{id\_loc}\K\.{'\\\\'};{}$\2\6
${}\|c\K{*}\\{loc}\PP;{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\PP\\{id\_loc}\Z\\{section\_text\_end}){}$\1\5
${}{*}\\{id\_loc}\K\|c;{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{id\_loc}\G\\{section\_text\_end}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"\\n!\ String\ too\ long}\)\.{:\ "});\6
${}\\{term\_write}(\\{section\_text}+\T{1},\39\T{25});{}$\6
\\{err\_print}(\.{"..."});\6
\4${}\}{}$\2\6
${}\\{id\_loc}\PP;{}$\6
\&{return} (\\{string});\6
\4${}\}{}$\2\par
\U87.\fi

\M{92}After an \.{@} sign has been scanned, the next character tells us
whether there is more work to do.

\Y\B\4\X92:Get control code and possible section name\X${}\E{}$\6
${}\{{}$\1\6
${}\|c\K\\{ccode}{}$[(\&{eight\_bits}) ${}{*}\\{loc}\PP];{}$\6
\&{switch} (\|c)\5
${}\{{}$\1\6
\4\&{case} \\{ignore}:\5
\&{continue};\6
\4\&{case} \\{output\_defs\_code}:\5
${}\\{output\_defs\_seen}\K\T{1};{}$\6
\&{return} (\|c);\6
\4\&{case} \\{translit\_code}:\5
\\{err\_print}(\.{"!\ Use\ @l\ in\ limbo\ o}\)\.{nly"});\6
\&{continue};\6
\4\&{case} \\{control\_text}:\6
\&{while} ${}((\|c\K\\{skip\_ahead}(\,))\E\.{'@'}){}$\1\5
;\C{ only \.{@@} and \.{@>} are expected }\2\6
\&{if} ${}({*}(\\{loc}-\T{1})\I\.{'>'}){}$\1\5
\\{err\_print}(\.{"!\ Double\ @\ should\ b}\)\.{e\ used\ in\ control\ te}\)%
\.{xt"});\2\6
\&{continue};\6
\4\&{case} \\{section\_name}:\5
${}\\{cur\_section\_name\_char}\K{*}(\\{loc}-\T{1});{}$\6
\X94:Scan the section name and make \PB{\\{cur\_section\_name}} point to it\X;\6
\4\&{case} \\{string}:\5
\X98:Scan a verbatim string\X;\6
\4\&{case} \\{ord}:\5
\X93:Scan an ASCII constant\X;\6
\4\&{default}:\5
\&{return} (\|c);\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\Q109.
\U87.\fi

\M{93}After scanning a valid ASCII constant that follows
\.{@'}, this code plows ahead until it finds the next single quote.
(Special care is taken if the quote is part of the constant.)
Anything after a valid ASCII constant is ignored;
thus, \.{@'\\nopq'} gives the same result as \.{@'\\n'}.

\Y\B\4\X93:Scan an ASCII constant\X${}\E{}$\6
$\\{id\_first}\K\\{loc};{}$\6
\&{if} ${}({*}\\{loc}\E\.{'\\\\'}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\PP\\{loc}\E\.{'\\''}){}$\1\5
${}\\{loc}\PP;{}$\2\6
\4${}\}{}$\2\6
\&{while} ${}({*}\\{loc}\I\.{'\\''}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{loc}\E\.{'@'}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}(\\{loc}+\T{1})\I\.{'@'}){}$\1\5
\\{err\_print}(\.{"!\ Double\ @\ should\ b}\)\.{e\ used\ in\ ASCII\ cons}\)%
\.{tant"});\2\6
\&{else}\1\5
${}\\{loc}\PP;{}$\2\6
\4${}\}{}$\2\6
${}\\{loc}\PP;{}$\6
\&{if} ${}(\\{loc}>\\{limit}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ String\ didn't\ end}\)\.{"});\6
${}\\{loc}\K\\{limit}-\T{1};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{loc}\PP;{}$\6
\&{return} (\\{ord});\par
\U92.\fi

\M{94}\B\X94:Scan the section name and make \PB{\\{cur\_section\_name}} point
to it\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\|k{}$;\C{ pointer into \PB{\\{section\_text}} }\7
\X96:Put section name into \PB{\\{section\_text}}\X;\6
\&{if} ${}(\|k-\\{section\_text}>\T{3}\W\\{strncmp}(\|k-\T{2},\39\.{"..."},\39%
\T{3})\E\T{0}){}$\1\5
${}\\{cur\_section\_name}\K\\{section\_lookup}(\\{section\_text}+\T{1},\39\|k-%
\T{3},\39\T{1}){}$;\C{ 1 means is a prefix }\2\6
\&{else}\1\5
${}\\{cur\_section\_name}\K\\{section\_lookup}(\\{section\_text}+\T{1},\39\|k,%
\39\T{0});{}$\2\6
\&{if} ${}(\\{cur\_section\_name\_char}\E\.{'('}){}$\1\5
\X46:If it's not there, add \PB{\\{cur\_section\_name}} to the output file
stack, or complain we're out of room\X;\2\6
\&{return} (\\{section\_name});\6
\4${}\}{}$\2\par
\U92.\fi

\M{95}Section names are placed into the \PB{\\{section\_text}} array with
consecutive spaces,
tabs, and carriage-returns replaced by single spaces. There will be no
spaces at the beginning or the end. (We set \PB{$\\{section\_text}[\T{0}]\K\.{'%
\ '}$} to facilitate
this, since the \PB{\\{section\_lookup}} routine uses \PB{\\{section\_text}[%
\T{1}]} as the first
character of the name.)

\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{section\_text}[\T{0}]\K\.{'\ '}{}$;\par
\fi

\M{96}\B\X96:Put section name into \PB{\\{section\_text}}\X${}\E{}$\6
$\|k\K\\{section\_text};{}$\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}>\\{limit}\W\\{get\_line}(\,)\E\T{0}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Input\ ended\ in\ se}\)\.{ction\ name"});\6
${}\\{loc}\K\\{buffer}+\T{1};{}$\6
\&{break};\6
\4${}\}{}$\2\6
${}\|c\K{*}\\{loc};{}$\6
\X97:If end of name or erroneous nesting, \PB{\&{break}}\X;\6
${}\\{loc}\PP;{}$\6
\&{if} ${}(\|k<\\{section\_text\_end}){}$\1\5
${}\|k\PP;{}$\2\6
\&{if} (\\{xisspace}(\|c))\5
${}\{{}$\1\6
${}\|c\K\.{'\ '};{}$\6
\&{if} ${}({*}(\|k-\T{1})\E\.{'\ '}){}$\1\5
${}\|k\MM;{}$\2\6
\4${}\}{}$\2\6
${}{*}\|k\K\|c;{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\|k\G\\{section\_text\_end}){}$\5
${}\{{}$\1\6
\\{printf}(\.{"\\n!\ Section\ name\ to}\)\.{o\ long:\ "});\6
${}\\{term\_write}(\\{section\_text}+\T{1},\39\T{25});{}$\6
\\{printf}(\.{"..."});\6
\\{mark\_harmless};\6
\4${}\}{}$\2\6
\&{if} ${}({*}\|k\E\.{'\ '}\W\|k>\\{section\_text}){}$\1\5
${}\|k\MM{}$;\2\par
\U94.\fi

\M{97}\B\X97:If end of name or erroneous nesting, \PB{\&{break}}\X${}\E{}$\6
\&{if} ${}(\|c\E\.{'@'}){}$\5
${}\{{}$\1\6
${}\|c\K{*}(\\{loc}+\T{1});{}$\6
\&{if} ${}(\|c\E\.{'>'}){}$\5
${}\{{}$\1\6
${}\\{loc}\MRL{+{\K}}\T{2};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} (\\{ccode}[(\&{eight\_bits}) \|c]${}\E\\{new\_section}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Section\ name\ didn}\)\.{'t\ end"});\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} (\\{ccode}[(\&{eight\_bits}) \|c]${}\E\\{section\_name}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Nesting\ of\ sectio}\)\.{n\ names\ not\ allowed"});\6
\&{break};\6
\4${}\}{}$\2\6
${}{*}(\PP\|k)\K\.{'@'};{}$\6
${}\\{loc}\PP{}$;\C{ now \PB{$\|c\E{*}\\{loc}$} again }\6
\4${}\}{}$\2\par
\U96.\fi

\M{98}At the present point in the program we
have \PB{${*}(\\{loc}-\T{1})\E\\{string}$}; we set \PB{\\{id\_first}} to the
beginning
of the string itself, and \PB{\\{id\_loc}} to its ending-plus-one location in
the
buffer.  We also set \PB{\\{loc}} to the position just after the ending
delimiter.

\Y\B\4\X98:Scan a verbatim string\X${}\E{}$\6
${}\{{}$\1\6
${}\\{id\_first}\K\\{loc}\PP;{}$\6
${}{*}(\\{limit}+\T{1})\K\.{'@'};{}$\6
${}{*}(\\{limit}+\T{2})\K\.{'>'};{}$\6
\&{while} ${}({*}\\{loc}\I\.{'@'}\V{*}(\\{loc}+\T{1})\I\.{'>'}){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{if} ${}(\\{loc}\G\\{limit}){}$\1\5
\\{err\_print}(\.{"!\ Verbatim\ string\ d}\)\.{idn't\ end"});\2\6
${}\\{id\_loc}\K\\{loc};{}$\6
${}\\{loc}\MRL{+{\K}}\T{2};{}$\6
\&{return} (\\{string});\6
\4${}\}{}$\2\par
\U92.\fi

\N{1}{99}Scanning a macro definition.
The rules for generating the replacement texts corresponding to macros and
\CEE/ texts of a section are almost identical; the only differences are that

\yskip \item{a)}Section names are not allowed in macros;
in fact, the appearance of a section name terminates such macros and denotes
the name of the current section.

\item{b)}The symbols \.{@d} and \.{@f} and \.{@c} are not allowed after
section names, while they terminate macro definitions.

\item{c)}Spaces are inserted after right parentheses in macros, because the
ANSI \CEE/ preprocessor sometimes requires it.

\yskip Therefore there is a single procedure \PB{\\{scan\_repl}} whose
parameter
\PB{\|t} specifies either \PB{\\{macro}} or \PB{\\{section\_name}}. After \PB{%
\\{scan\_repl}} has
acted, \PB{\\{cur\_text}} will point to the replacement text just generated,
and
\PB{\\{next\_control}} will contain the control code that terminated the
activity.

\Y\B\4\D$\\{macro}$ \5
\T{0}\par
\B\4\D$\\{app\_repl}(\|c)$ \6
${}\{{}$\1\6
\&{if} ${}(\\{tok\_ptr}\E\\{tok\_mem\_end}){}$\1\5
\\{overflow}(\.{"token"});\2\6
${}{*}\\{tok\_ptr}\PP\K\|c;{}$\6
\4${}\}{}$\2\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{text\_pointer} \\{cur\_text};\C{ replacement text formed by \PB{\\{scan%
\_repl}} }\6
\&{eight\_bits} \\{next\_control};\par
\fi

\M{100}\B\&{void} \\{scan\_repl}(\|t)\C{ creates a replacement text }\1\1\6
\&{eight\_bits} \|t;\2\2\6
${}\{{}$\1\6
\&{sixteen\_bits} \|a;\C{ the current token }\7
\&{if} ${}(\|t\E\\{section\_name}){}$\5
${}\{{}$\1\6
\X101:Insert the line number into \PB{\\{tok\_mem}}\X;\6
\4${}\}{}$\2\6
\&{while} (\T{1})\1\6
\&{switch} ${}(\|a\K\\{get\_next}(\,)){}$\5
${}\{{}$\1\6
\4\\{got\_next\_one}:\5
\X102:In cases that \PB{\|a} is a non-\PB{\&{char}} token (\PB{\\{identifier}},
\PB{\\{section\_name}}, etc.), either process it and change \PB{\|a} to a byte
that should be stored, or \PB{\&{continue}} if \PB{\|a} should be ignored, or %
\PB{\&{goto} \\{done}} if \PB{\|a} signals the end of this replacement text\X\6
\4\&{case} \.{')'}:\5
\\{app\_repl}(\|a);\6
\&{if} ${}(\|t\E\\{macro}){}$\1\5
\\{app\_repl}(\.{'\ '});\2\6
\&{break};\6
\4\&{default}:\5
\\{app\_repl}(\|a);\C{ store \PB{\|a} in \PB{\\{tok\_mem}} }\6
\4${}\}{}$\2\2\6
\4\\{done}:\5
${}\\{next\_control}\K{}$(\&{eight\_bits}) \|a;\6
\&{if} ${}(\\{text\_ptr}>\\{text\_info\_end}){}$\1\5
\\{overflow}(\.{"text"});\2\6
${}\\{cur\_text}\K\\{text\_ptr};{}$\6
${}(\PP\\{text\_ptr})\MG\\{tok\_start}\K\\{tok\_ptr};{}$\6
\4${}\}{}$\2\par
\fi

\M{101}Here is the code for the line number: first a \PB{\&{sixteen\_bits}}
equal
to \PB{\T{\~150000}}; then the numeric line number; then a pointer to the
file name.

\Y\B\4\X101:Insert the line number into \PB{\\{tok\_mem}}\X${}\E{}$\6
\\{store\_two\_bytes}(\T{\~150000});\6
\&{if} (\\{changing})\1\5
${}\\{id\_first}\K\\{change\_file\_name};{}$\2\6
\&{else}\1\5
${}\\{id\_first}\K\\{cur\_file\_name};{}$\2\6
${}\\{id\_loc}\K\\{id\_first}+\\{strlen}(\\{id\_first});{}$\6
\&{if} (\\{changing})\1\5
\\{store\_two\_bytes}((\&{sixteen\_bits}) \\{change\_line});\2\6
\&{else}\1\5
\\{store\_two\_bytes}((\&{sixteen\_bits}) \\{cur\_line});\2\6
${}\{{}$\1\6
\&{int} \|a${}\K\\{id\_lookup}(\\{id\_first},\39\\{id\_loc},\39\T{0})-\\{name%
\_dir};{}$\7
${}\\{app\_repl}((\|a/\T{\~400})+\T{\~200});{}$\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\4${}\}{}$\2\par
\Us87, 100\ETs102.\fi

\M{102}\B\X102:In cases that \PB{\|a} is a non-\PB{\&{char}} token (\PB{%
\\{identifier}}, \PB{\\{section\_name}}, etc.), either process it and change %
\PB{\|a} to a byte that should be stored, or \PB{\&{continue}} if \PB{\|a}
should be ignored, or \PB{\&{goto} \\{done}} if \PB{\|a} signals the end of
this replacement text\X${}\E{}$\6
\4\&{case} \\{special\_command}:\5
${}\|a\K\\{get\_next}(\,);{}$\6
\X103:Special command seen in \CEE/ text\X;\6
\&{goto} \\{got\_next\_one};\C{ already holding next token }\6
\4\&{case} \\{identifier}:\5
${}\|a\K\\{id\_lookup}(\\{id\_first},\39\\{id\_loc},\39\T{0})-\\{name\_dir};{}$%
\6
${}\\{app\_repl}((\|a/\T{\~400})+\T{\~200});{}$\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\&{break};\6
\4\&{case} \\{section\_name}:\6
\&{if} ${}(\|t\I\\{section\_name}){}$\1\5
\&{goto} \\{done};\2\6
\&{else}\5
${}\{{}$\1\6
\X104:Was an `@' missed here?\X;\6
${}\|a\K\\{cur\_section\_name}-\\{name\_dir};{}$\6
${}\\{app\_repl}((\|a/\T{\~400})+\T{\~250});{}$\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\X101:Insert the line number into \PB{\\{tok\_mem}}\X;\6
\&{break};\6
\4${}\}{}$\2\6
\4\&{case} \\{output\_defs\_code}:\5
${}\|a\K\\{output\_defs\_flag};{}$\6
${}\\{app\_repl}((\|a/\T{\~400})+\T{\~200});{}$\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\X101:Insert the line number into \PB{\\{tok\_mem}}\X;\6
\&{break};\6
\4\&{case} \\{constant}:\5
\&{case} \\{string}:\5
\X105:Copy a string or verbatim construction or numerical constant\X;\6
\4\&{case} \\{ord}:\5
\X106:Copy an ASCII constant\X;\6
\4\&{case} \\{definition}:\5
\&{case} \\{format\_code}:\5
\&{case} \\{begin\_C}:\6
\&{if} ${}(\|t\I\\{section\_name}){}$\1\5
\&{goto} \\{done};\2\6
\&{else}\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ @d,\ @f\ and\ @c\ are}\)\.{\ ignored\ in\ C\ text"});\6
\&{continue};\6
\4${}\}{}$\2\6
\4\&{case} \\{new\_section}:\5
\&{goto} \\{done};\par
\U100.\fi

\M{103}%mine
A special command introduced by \.{@\_} was seen while scanning
the \CEE/ text of a section. If it's an export statement like \&{global},
we remember it, so that we can parse the following declaration when we
reach the end of the section.
The same applies to import commands like \&{import}.
\Y\B\4\X103:Special command seen in \CEE/ text\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\|a\E\\{identifier}){}$\5
${}\{{}$\1\6
${}\|a\K\\{id\_lookup}(\\{id\_first},\39\\{id\_loc},\39\T{0})-\\{name\_dir};{}$%
\6
\&{if} ${}(\\{id\_global}\Z\|a\W\|a\Z\\{id\_shared}){}$\5
${}\{{}$\1\6
\\{remember\_export}(\|a);\6
\&{break};\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{id\_import}\E\|a\V\|a\E\\{id\_from}){}$\5
${}\{{}$\1\6
\\{remember\_import}(\,);\6
${}\\{app\_repl}((\|a/\T{\~400})+\T{\~200});{}$\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{id\_mark}\E\|a\V\\{id\_paste}\E\|a){}$\5
${}\{{}$\C{ ignore it and the string following }\1\6
${}\|a\K\\{get\_next}(\,);{}$\6
\&{if} ${}(\|a\E\\{string}){}$\1\5
\&{break};\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{id\_copy}\E\|a){}$\1\5
\&{break};\C{ ignore it }\2\6
\4${}\}{}$\2\6
\\{err\_print}(\.{"!\ Illegal\ special\ c}\)\.{ommand"});\6
\4${}\}{}$\2\par
\U102.\fi

\M{104}\B\X104:Was an `@' missed here?\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{try\_loc}\K\\{loc};{}$\7
\&{while} ${}({*}\\{try\_loc}\E\.{'\ '}\W\\{try\_loc}<\\{limit}){}$\1\5
${}\\{try\_loc}\PP;{}$\2\6
\&{if} ${}({*}\\{try\_loc}\E\.{'+'}\W\\{try\_loc}<\\{limit}){}$\1\5
${}\\{try\_loc}\PP;{}$\2\6
\&{while} ${}({*}\\{try\_loc}\E\.{'\ '}\W\\{try\_loc}<\\{limit}){}$\1\5
${}\\{try\_loc}\PP;{}$\2\6
\&{if} ${}({*}\\{try\_loc}\E\.{'='}){}$\1\5
\\{err\_print}(\.{"!\ Missing\ `@\ '\ befo}\)\.{re\ a\ named\ section"});\C{
user who isn't defining a section should put newline after the name,      as
explained in the manual }\2\6
\4${}\}{}$\2\par
\U102.\fi

\M{105}\B\X105:Copy a string or verbatim construction or numerical constant%
\X${}\E{}$\6
\\{app\_repl}(\|a);\C{ \PB{\\{string}} or \PB{\\{constant}} }\6
\&{while} ${}(\\{id\_first}<\\{id\_loc}){}$\5
${}\{{}$\C{ simplify \.{@@} pairs }\1\6
\&{if} ${}({*}\\{id\_first}\E\.{'@'}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}(\\{id\_first}+\T{1})\E\.{'@'}){}$\1\5
${}\\{id\_first}\PP;{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Double\ @\ should\ b}\)\.{e\ used\ in\ string"});\2\6
\4${}\}{}$\2\6
${}\\{app\_repl}({*}\\{id\_first}\PP);{}$\6
\4${}\}{}$\2\6
\\{app\_repl}(\|a);\6
\&{break};\par
\U102.\fi

\M{106}This section should be rewritten on machines that don't use ASCII
code internally.

\Y\B\4\X106:Copy an ASCII constant\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|c${}\K{}$(\&{eight\_bits}) ${}{*}\\{id\_first};{}$\7
\&{if} ${}(\|c\E\.{'\\\\'}){}$\5
${}\{{}$\1\6
${}\|c\K{*}\PP\\{id\_first};{}$\6
\&{if} ${}(\|c\G\.{'0'}\W\|c\Z\.{'7'}){}$\5
${}\{{}$\1\6
${}\|c\MRL{-{\K}}\.{'0'};{}$\6
\&{if} ${}({*}(\\{id\_first}+\T{1})\G\.{'0'}\W{*}(\\{id\_first}+\T{1})\Z%
\.{'7'}){}$\5
${}\{{}$\1\6
${}\|c\K\T{8}*\|c+{*}(\PP\\{id\_first})-\.{'0'};{}$\6
\&{if} ${}({*}(\\{id\_first}+\T{1})\G\.{'0'}\W{*}(\\{id\_first}+\T{1})\Z\.{'7'}%
\W\|c<\T{32}){}$\1\5
${}\|c\K\T{8}*\|c+{*}(\PP\\{id\_first})-\.{'0'};{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\6
\&{switch} (\|c)\5
${}\{{}$\1\6
\4\&{case} \.{'t'}:\5
${}\|c\K\.{'\\t'}{}$;\5
\&{break};\6
\4\&{case} \.{'n'}:\5
${}\|c\K\.{'\\n'}{}$;\5
\&{break};\6
\4\&{case} \.{'b'}:\5
${}\|c\K\.{'\\b'}{}$;\5
\&{break};\6
\4\&{case} \.{'f'}:\5
${}\|c\K\.{'\\f'}{}$;\5
\&{break};\6
\4\&{case} \.{'v'}:\5
${}\|c\K\.{'\\v'}{}$;\5
\&{break};\6
\4\&{case} \.{'r'}:\5
${}\|c\K\.{'\\r'}{}$;\5
\&{break};\6
\4\&{case} \.{'a'}:\5
${}\|c\K\.{'\\7'}{}$;\5
\&{break};\6
\4\&{case} \.{'?'}:\5
${}\|c\K\.{'?'}{}$;\5
\&{break};\6
\4\&{case} \.{'x'}:\6
\&{if} ${}(\\{xisdigit}({*}(\\{id\_first}+\T{1}))){}$\1\5
${}\|c\K{*}(\PP\\{id\_first})-\.{'0'};{}$\2\6
\&{else} \&{if} ${}(\\{xisxdigit}({*}(\\{id\_first}+\T{1}))){}$\5
${}\{{}$\1\6
${}\PP\\{id\_first};{}$\6
${}\|c\K\\{toupper}({*}\\{id\_first})-\.{'A'}+\T{10};{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{xisdigit}({*}(\\{id\_first}+\T{1}))){}$\1\5
${}\|c\K\T{16}*\|c+{*}(\PP\\{id\_first})-\.{'0'};{}$\2\6
\&{else} \&{if} ${}(\\{xisxdigit}({*}(\\{id\_first}+\T{1}))){}$\5
${}\{{}$\1\6
${}\PP\\{id\_first};{}$\6
${}\|c\K\T{16}*\|c+\\{toupper}({*}\\{id\_first})-\.{'A'}+\T{10};{}$\6
\4${}\}{}$\2\6
\&{break};\6
\4\&{case} \.{'\\\\'}:\5
${}\|c\K\.{'\\\\'}{}$;\5
\&{break};\6
\4\&{case} \.{'\\''}:\5
${}\|c\K\.{'\\''}{}$;\5
\&{break};\6
\4\&{case} \.{QUOTE}:\5
${}\|c\K\.{QUOTE}{}$;\5
\&{break};\6
\4\&{default}:\5
\\{err\_print}(\.{"!\ Unrecognized\ esca}\)\.{pe\ sequence"});\6
\4${}\}{}$\2\2\6
\4${}\}{}$\C{ at this point \PB{\|c} should have been converted to its ASCII
code number }\2\6
\\{app\_repl}(\\{constant});\6
\&{if} ${}(\|c\G\T{100}){}$\1\5
${}\\{app\_repl}(\.{'0'}+\|c/\T{100});{}$\2\6
\&{if} ${}(\|c\G\T{10}){}$\1\5
${}\\{app\_repl}(\.{'0'}+(\|c/\T{10})\MOD\T{10});{}$\2\6
${}\\{app\_repl}(\.{'0'}+\|c\MOD\T{10});{}$\6
\\{app\_repl}(\\{constant});\6
\4${}\}{}$\2\6
\&{break};\par
\U102.\fi

\N{1}{107}Scanning a section.
The \PB{\\{scan\_section}} procedure starts when `\.{@\ }' or `\.{@*}' has been
sensed in the input, and it proceeds until the end of that section.  It
uses \PB{\\{section\_count}} to keep track of the current section number; with
luck,
\.{CWEAVE} and \.{CTANGLE} will both assign the same numbers to sections.

\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{extern} \&{sixteen\_bits} \\{section\_count};\C{ the current section number
}\par
\fi

\M{108}The body of \PB{\\{scan\_section}} is a loop where we look for control
codes
that are significant to \.{CTANGLE}: those
that delimit a definition, the \CEE/ part of a module, or a new module.

\Y\B\&{void} \\{scan\_section}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{name\_pointer} \|p;\C{ section name for the current section }\6
\&{text\_pointer} \|q;\C{ text for the current section }\6
\&{sixteen\_bits} \|a;\C{ token for left-hand side of definition }\7
${}\\{section\_count}\PP{}$;\5
${}\\{no\_where}\K\T{1};{}$\6
\&{if} ${}({*}(\\{loc}-\T{1})\E\.{'*'}\W\\{show\_progress}){}$\5
${}\{{}$\C{ starred section }\1\6
${}\\{printf}(\.{"*\%d"},\39\\{section\_count});{}$\6
\\{update\_terminal};\6
\4${}\}{}$\2\6
${}\\{next\_control}\K\T{0};{}$\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\X109:Skip ahead until \PB{\\{next\_control}} corresponds to \.{@d}, \.{@<}, %
\.{@\ } or the like\X;\6
\&{if} ${}(\\{next\_control}\E\\{definition}){}$\5
${}\{{}$\C{ \.{@d} }\1\6
\X110:Scan a definition\X\6
\&{continue};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{next\_control}\E\\{begin\_C}){}$\5
${}\{{}$\C{ \.{@c} or \.{@p} }\1\6
${}\|p\K\\{name\_dir};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{next\_control}\E\\{section\_name}){}$\5
${}\{{}$\C{ \.{@<} or \.{@(} }\1\6
${}\|p\K\\{cur\_section\_name};{}$\6
\X112:If section is not being defined, \PB{\&{continue}}\X;\6
\&{break};\6
\4${}\}{}$\2\6
\&{return};\C{ \.{@\ } or \.{@*} }\6
\4${}\}{}$\2\6
${}\\{no\_where}\K\\{print\_where}\K\T{0};{}$\6
\X113:Scan the \CEE/ part of the current section\X;\6
\4${}\}{}$\2\par
\fi

\M{109}At the top of this loop, if \PB{$\\{next\_control}\E\\{section\_name}$},
the
section name has already been scanned (see \PB{$\X92:Get control code and
possible section name\X$}).  Thus, if we encounter \PB{$\\{next\_control}\E%
\\{section\_name}$} in the
skip-ahead process, we should likewise scan the section name, so later
processing will be the same in both cases.

\Y\B\4\X109:Skip ahead until \PB{\\{next\_control}} corresponds to \.{@d}, %
\.{@<}, \.{@\ } or the like\X${}\E{}$\6
\&{while} ${}(\\{next\_control}<\\{definition}{}$)\C{ \PB{\\{definition}} is
the lowest of the ``significant'' codes }\1\6
\&{if} ${}((\\{next\_control}\K\\{skip\_ahead}(\,))\E\\{section\_name}){}$\5
${}\{{}$\1\6
${}\\{loc}\MRL{-{\K}}\T{2};{}$\6
${}\\{next\_control}\K\\{get\_next}(\,);{}$\6
\4${}\}{}$\2\2\par
\U108.\fi

\M{110}\B\X110:Scan a definition\X${}\E{}$\6
${}\{{}$\1\6
\X111:Handle export commands in definitions\X;\6
\&{if} ${}(\\{next\_control}\I\\{identifier}){}$\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Definition\ flushe}\)\.{d,\ must\ start\ with\ i}\)%
\.{dentifier"});\6
\&{continue};\6
\4${}\}{}$\2\6
${}\\{app\_repl}(((\|a\K\\{id\_lookup}(\\{id\_first},\39\\{id\_loc},\39\T{0})-%
\\{name\_dir})/\T{\~400})+\T{\~200}){}$;\C{ append the lhs }\6
${}\\{app\_repl}(\|a\MOD\T{\~400});{}$\6
\&{if} ${}({*}\\{loc}\I\.{'('}){}$\5
${}\{{}$\C{ identifier must be separated from replacement text }\1\6
\\{app\_repl}(\\{string});\6
\\{app\_repl}(\.{'\ '});\6
\\{app\_repl}(\\{string});\6
\4${}\}{}$\2\6
\\{scan\_repl}(\\{macro});\6
${}\\{cur\_text}\MG\\{text\_link}\K\T{0}{}$;\C{ \PB{$\\{text\_link}\E\T{0}$}
characterizes a macro }\6
\4${}\}{}$\2\par
\U108.\fi

\M{111}%mine
When we scan a definition, we want to include the section number
\PB{\\{section\_count}} which indicates where it was defined as a comment
which will precede the actual definition in the token list we are creating.
This comment is parsed by \PB{\\{output\_defs}}. We need this comment in order
to inform \.{mCWEAVE} where the definition came from, since
\.{mCWEAVE} will be reading our export files in order to make its index.

The comment in the token memory may further be followed by one or more
export special commands like \&{export} before the actual definition starts.
\Y\B\4\X111:Handle export commands in definitions\X${}\E{}$\6
${}\{{}$\1\6
\&{char} \\{comment}[\T{20}]${},{}$ ${}{*}\\{cp};{}$\7
\&{while} ${}((\\{next\_control}\K\\{get\_next}(\,))\E\.{'\\n'}){}$\1\5
;\C{allow newline before definition }\2\6
${}\\{sprintf}(\\{comment},\39\.{"\\03/*Section:\%d*/\\0}\)\.{3"},\39\\{section%
\_count});{}$\6
\&{for} ${}(\\{cp}\K\\{comment};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{cp});{}$\2\6
\&{while} ${}(\\{next\_control}\E\\{special\_command}){}$\5
${}\{{}$\1\6
${}\\{next\_control}\K\\{get\_next}(\,);{}$\6
\&{if} ${}(\\{next\_control}\E\\{identifier}){}$\5
${}\{{}$\1\6
${}\|a\K\\{id\_lookup}(\\{id\_first},\39\\{id\_loc},\39\T{0})-\\{name\_dir};{}$%
\6
\&{if} ${}(\\{id\_global}\Z\|a\W\|a\Z\\{id\_shared}){}$\5
${}\{{}$\1\6
${}\\{used\_exports}\MRL{{\OR}{\K}}\T{1}\LL\|a-\T{1}{}$;\C{ remember that we
saw this export command }\6
\\{app\_repl}(\\{special\_command});\6
${}\\{app\_repl}((\|a\GG\T{8})+\T{\~200}){}$;\C{ append the export command }\6
${}\\{app\_repl}(\|a\AND\T{\~377});{}$\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Illegal\ export\ co}\)\.{mmand"});\6
\&{break};\6
\4${}\}{}$\2\6
\&{do}\5
${}\\{next\_control}\K\\{get\_next}(\,);{}$\5
\&{while} (\\{xisspace}(\\{next\_control}));\6
\4${}\}{}$\2\6
\&{else}\1\5
\&{break};\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U110.\fi

\M{112}If the section name is not followed by \.{=} or \.{+=}, no \CEE/
code is forthcoming: the section is being cited, not being
defined.  This use is illegal after the definition part of the
current section has started, except inside a comment, but
\.{CTANGLE} does not enforce this rule: it simply ignores the offending
section name and everything following it, up to the next significant
control code.

\Y\B\4\X112:If section is not being defined, \PB{\&{continue}}\X${}\E{}$\6
\&{while} ${}((\\{next\_control}\K\\{get\_next}(\,))\E\.{'+'}){}$\1\5
;\C{ allow optional \.{+=} }\2\6
\&{if} ${}(\\{next\_control}\I\.{'='}\W\\{next\_control}\I\\{eq\_eq}){}$\1\5
\&{continue};\2\par
\U108.\fi

\M{113}%modified
\Y\B\4\X113:Scan the \CEE/ part of the current section\X${}\E{}$\6
\X114:Insert the section number into \PB{\\{tok\_mem}}\X;\6
\\{scan\_repl}(\\{section\_name});\C{ now \PB{\\{cur\_text}} points to the
replacement text }\6
\X115:Update the data structure so that the replacement text is accessible\X;\6
\\{process\_imports}(\,);\C{ process all import commands of this section }\6
\\{process\_exports}(\,);\C{ process all export commands of this section }\par
\U108.\fi

\M{114}\B\X114:Insert the section number into \PB{\\{tok\_mem}}\X${}\E{}$\6
\\{store\_two\_bytes}((\&{sixteen\_bits}) ${}(\T{\~150000}+\\{section%
\_count})){}$;\C{ \PB{$\T{\~150000}\E\T{\~320}*\T{\~400}$} }\par
\U113.\fi

\M{115}\B\X115:Update the data structure so that the replacement text is
accessible\X${}\E{}$\6
\&{if} ${}(\|p\E\\{name\_dir}\V\|p\E\T{0}){}$\5
${}\{{}$\C{ unnamed section, or bad section name }\1\6
${}(\\{last\_unnamed})\MG\\{text\_link}\K\\{cur\_text}-\\{text\_info};{}$\6
${}\\{last\_unnamed}\K\\{cur\_text};{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\|p\MG\\{equiv}\E{}$(\&{char} ${}{*}){}$ \\{text\_info})\1\5
${}\|p\MG\\{equiv}\K{}$(\&{char} ${}{*}){}$ \\{cur\_text};\C{ first section of
this name }\2\6
\&{else}\5
${}\{{}$\1\6
${}\|q\K{}$(\&{text\_pointer}) \|p${}\MG\\{equiv};{}$\6
\&{while} ${}(\|q\MG\\{text\_link}<\\{section\_flag}){}$\1\5
${}\|q\K\|q\MG\\{text\_link}+\\{text\_info}{}$;\C{ find end of list }\2\6
${}\|q\MG\\{text\_link}\K\\{cur\_text}-\\{text\_info};{}$\6
\4${}\}{}$\2\6
${}\\{cur\_text}\MG\\{text\_link}\K\\{section\_flag}{}$;\C{ mark this
replacement text as a nonmacro }\par
\U113.\fi

\M{116}\B\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{phase\_one}(\,);\par
\fi

\M{117}\B\&{void} \\{phase\_one}(\,)\1\1\2\2\6
${}\{{}$\1\6
${}\\{phase}\K\T{1};{}$\6
${}\\{section\_count}\K\T{0};{}$\6
\\{reset\_input}(\,);\6
\\{skip\_limbo}(\,);\6
\&{while} ${}(\R\\{input\_has\_ended}){}$\1\5
\\{scan\_section}(\,);\2\6
\\{check\_complete}(\,);\6
${}\\{phase}\K\T{2};{}$\6
\4${}\}{}$\2\par
\fi

\M{118}Only a small subset of the control codes is legal in limbo, so limbo
processing is straightforward.

\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{skip\_limbo}(\,);\par
\fi

\M{119}\B\&{void} \\{skip\_limbo}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{char} \|c;\7
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\\{loc}>\\{limit}\W\\{get\_line}(\,)\E\T{0}){}$\1\5
\&{return};\2\6
${}{*}(\\{limit}+\T{1})\K\.{'@'};{}$\6
\&{while} ${}({*}\\{loc}\I\.{'@'}){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{if} ${}(\\{loc}\PP\Z\\{limit}){}$\5
${}\{{}$\1\6
${}\|c\K{*}\\{loc}\PP;{}$\6
\&{if} (\\{ccode}[(\&{eight\_bits}) \|c]${}\E\\{new\_section}){}$\1\5
\&{break};\2\6
\&{switch} (\\{ccode}[(\&{eight\_bits}) \|c])\5
${}\{{}$\1\6
\4\&{case} \\{translit\_code}:\5
\X120:Read in transliteration of a character\X;\6
\&{break};\6
\4\&{case} \\{format\_code}:\5
\&{case} \.{'@'}:\5
\&{break};\6
\4\&{case} \\{control\_text}:\6
\&{if} ${}(\|c\E\.{'q'}\V\|c\E\.{'Q'}){}$\5
${}\{{}$\1\6
\&{while} ${}((\|c\K\\{skip\_ahead}(\,))\E\.{'@'}){}$\1\5
;\2\6
\&{if} ${}({*}(\\{loc}-\T{1})\I\.{'>'}){}$\1\5
\\{err\_print}(\.{"!\ Double\ @\ should\ b}\)\.{e\ used\ in\ control\ te}\)%
\.{xt"});\2\6
\&{break};\6
\4${}\}{}$\C{ otherwise fall through }\2\6
\4\&{default}:\5
\\{err\_print}(\.{"!\ Double\ @\ should\ b}\)\.{e\ used\ in\ limbo"});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{120}\B\X120:Read in transliteration of a character\X${}\E{}$\6
\&{while} ${}(\\{xisspace}({*}\\{loc})\W\\{loc}<\\{limit}){}$\1\5
${}\\{loc}\PP;{}$\2\6
${}\\{loc}\MRL{+{\K}}\T{3};{}$\6
\&{if} ${}(\\{loc}>\\{limit}\V\R\\{xisxdigit}({*}(\\{loc}-\T{3}))\V\R%
\\{xisxdigit}({*}(\\{loc}-\T{2}))\3{-1}\V({*}(\\{loc}-\T{3})\G\.{'0'}\W{*}(%
\\{loc}-\T{3})\Z\.{'7'})\V\R\\{xisspace}({*}(\\{loc}-\T{1}))){}$\1\5
\\{err\_print}(\.{"!\ Improper\ hex\ numb}\)\.{er\ following\ @l"});\2\6
\&{else}\5
${}\{{}$\1\6
\&{unsigned} \|i;\6
\&{char} ${}{*}\\{beg};{}$\7
${}\\{sscanf}(\\{loc}-\T{3},\39\.{"\%x"},\39{\AND}\|i);{}$\6
\&{while} ${}(\\{xisspace}({*}\\{loc})\W\\{loc}<\\{limit}){}$\1\5
${}\\{loc}\PP;{}$\2\6
${}\\{beg}\K\\{loc};{}$\6
\&{while} ${}(\\{loc}<\\{limit}\W(\\{xisalpha}({*}\\{loc})\V\\{xisdigit}({*}%
\\{loc})\V{*}\\{loc}\E\.{'\_'})){}$\1\5
${}\\{loc}\PP;{}$\2\6
\&{if} ${}(\\{loc}-\\{beg}\G\\{translit\_length}){}$\1\5
\\{err\_print}(\.{"!\ Replacement\ strin}\)\.{g\ in\ @l\ too\ long"});\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{strncpy}(\\{translit}[\|i-\T{\~200}],\39\\{beg},\39\\{loc}-\\{beg});{}$\6
${}\\{translit}[\|i-\T{\~200}][\\{loc}-\\{beg}]\K\.{'\\0'};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U119.\fi

\M{121}Because on some systems the difference between two pointers is a \PB{%
\&{long}}
but not an \PB{\&{int}}, we use \.{\%ld} to print these quantities.

\Y\B\&{void} \\{print\_stats}(\,)\1\1\2\2\6
${}\{{}$\1\6
\\{printf}(\.{"\\nMemory\ usage\ stat}\)\.{istics:\\n"});\6
${}\\{printf}(\.{"\%ld\ names\ (out\ of\ \%}\)\.{ld)\\n"},\39{}$(\&{long}) ${}(%
\\{name\_ptr}-\\{name\_dir}),\39{}$(\&{long}) \\{max\_names});\6
${}\\{printf}(\.{"\%ld\ replacement\ tex}\)\.{ts\ (out\ of\ \%ld)\\n"},\39{}$(%
\&{long}) ${}(\\{text\_ptr}-\\{text\_info}),\39{}$(\&{long}) \\{max\_texts});\6
${}\\{printf}(\.{"\%ld\ bytes\ (out\ of\ \%}\)\.{ld)\\n"},\39{}$(\&{long}) ${}(%
\\{byte\_ptr}-\\{byte\_mem}),\39{}$(\&{long}) \\{max\_bytes});\6
${}\\{printf}(\.{"\%ld\ tokens\ (out\ of\ }\)\.{\%ld)\\n"},\39{}$(\&{long})
${}(\\{tok\_ptr}-\\{tok\_mem}),\39{}$(\&{long}) \\{max\_toks});\6
\4${}\}{}$\2\par
\fi

\N{0}{122}Multiple files.
I've tried to concentrate most of the extensions of \.{mCTANGLE}
concerning multiple file support in this section. Nevertheless,
numerous changes to the preceding sections were inevitable.
However, everything from here on is completely \.{mCWEB}-specific.

\fi

\N{1}{123}Export commands.
\.{mCTANGLE} has been modified so that it now can export and import
code from one \.{CWEB} file to another.
Now we want to treat all commands that are dealing with export.

\fi

\M{124}The following constants are used in order to form a bit mask which
describes where to export our \CEE/ statements. It can be
calculated by $1<<id\_\ldots-1$. \PB{\\{used\_exports}} indicates
all export commands that have been used in this file.
\Y\B\4\D$\\{exp\_global}$ \5
\T{1}\par
\B\4\D$\\{exp\_export}$ \5
\T{2}\par
\B\4\D$\\{exp\_shared}$ \5
\T{4}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{sixteen\_bits} \\{used\_exports};\par
\fi

\M{125}
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{used\_exports}\K\T{0}{}$;\par
\fi

\M{126}If we encounter an export command (e.g.~\&{global}), we store the
current
\PB{\\{tok\_ptr}} in \PB{\\{export\_ref}}. The corresponding \PB{\\{export%
\_type}} indicates the type
of export (e.g.~\PB{\\{exp\_global}}). In addition, we remember the line and
file name
where the export command was found.

But if the value of \PB{\\{tok\_ptr}} has not changed since the last export
command,
we only modify \PB{\\{export\_type}} because this is an additional
export qualifier for the last command (e.g.~\&{export} \&{shared}).
All the stored export references are processed at the end of the
current section.
\Y\B\4\D$\\{max\_exports}$ \5
\T{64}\C{ maximum of export commands per section }\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{eight\_bits} ${}{*}\\{export\_ref}[\\{max\_exports}]{}$;\C{ points into \PB{%
\\{tok\_mem}} }\6
\&{eight\_bits} \\{export\_type}[\\{max\_exports}];\C{ mask of \PB{\\{exp%
\_shared}}, etc. }\6
\&{int} \\{export\_line}[\\{max\_exports}];\C{ line number where export command
was found }\6
\&{char} ${}{*}\\{export\_file\_name}[\\{max\_exports}]{}$;\C{ pointer to
source file name }\6
\&{sixteen\_bits} \\{export\_idx};\par
\fi

\M{127}This a counter for our export commands of the current section.
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{export\_idx}\K\T{0}{}$;\par
\fi

\M{128}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{remember\_export}(\,);\par
\fi

\M{129}This is called every time \PB{\\{scan\_repl}} sees an export command
like
\&{global}.
\Y\B\&{void} \\{remember\_export}(\\{id})\1\1\6
\&{sixteen\_bits} \\{id};\2\2\6
${}\{{}$\1\6
\&{sixteen\_bits} \|c;\7
${}\|c\K\T{1}\LL\\{id}-\T{1}{}$;\C{ calculate export mask ($id\_\ldots%
\rightarrow exp\_\ldots$) }\6
${}\\{used\_exports}\MRL{{\OR}{\K}}\|c;{}$\6
\&{if} ${}(\\{export\_idx}\W\\{export\_ref}[\\{export\_idx}-\T{1}]\E\\{tok%
\_ptr}{}$)\C{ same token position as last time }\1\6
${}\\{export\_type}[\\{export\_idx}-\T{1}]\MRL{{\OR}{\K}}\|c{}$;\C{ $%
\rightarrow$ additional export qualifier }\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{export\_idx}\G\\{max\_exports}){}$\1\5
\\{overflow}(\.{"exports\ per\ section}\)\.{"});\2\6
${}\\{export\_ref}[\\{export\_idx}]\K\\{tok\_ptr};{}$\6
${}\\{export\_type}[\\{export\_idx}]\K\|c;{}$\6
${}\\{export\_line}[\\{export\_idx}]\K\\{changing}\?\\{change\_line}:\\{cur%
\_line};{}$\6
${}\\{export\_file\_name}[\\{export\_idx}]\K\\{changing}\?\\{change\_file%
\_name}:\\{cur\_file\_name};{}$\6
${}\\{export\_idx}\PP;{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{130}When we are reading the source file, we will find some export
commands. For every command, we will analyze the following
statement. After we know what it is, we modify the
original token list and additionally insert a modified version
in an export section.

There are the following catagories of export
sections for every export type (global, export, shared):
\Y\B\4\D$\\{forward\_types}$ \5
\T{0}\C{ forward declarations of \CPLUSPLUS/ classes }\par
\B\4\D$\\{types}$ \5
\T{1}\C{ \PB{\&{typedef}} and aggregates }\par
\B\4\D$\\{declarations}$ \5
\T{2}\C{ variable declarations and function prototypes }\par
\B\4\D$\\{num\_export\_sections}$ \5
\T{3}\C{ number of export sections per type }\par
\Y\B\4\X18:Typedef declarations\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{text\_pointer} \\{first\_text};\C{ first \PB{\&{text}} for this export
section }\6
\&{text\_pointer} \\{last\_text};\C{ last \PB{\&{text}} for this export section
}\2\6
${}\}{}$ \&{export\_section};\par
\fi

\M{131}
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{export\_section} \\{glb\_sec}[\\{num\_export\_sections}];\C{ export sections
for \&{global} }\6
\&{export\_section} \\{exp\_sec}[\\{num\_export\_sections}];\6
\&{export\_section} \\{shr\_sec}[\\{num\_export\_sections}];\6
\&{export\_section} \\{var\_sec};\C{ where all variable definitions go }\par
\fi

\M{132}
\Y\B\4\D$\\{clear\_export\_sections}(\|s)$ \5
\\{memset}((\&{void} ${}{*}){}$ \|s${},\39\T{0},\39{}$\&{sizeof} (\\{glb%
\_sec}))\par
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
\\{clear\_export\_sections}(\\{glb\_sec});\6
\\{clear\_export\_sections}(\\{exp\_sec});\6
\\{clear\_export\_sections}(\\{shr\_sec});\6
\\{memset}((\&{void} ${}{*}){}$ ${}{\AND}\\{var\_sec},\39\T{0},\39{}$\&{sizeof}
(\\{var\_sec}));\par
\fi

\M{133}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{push\_export\_section}(\,);\par
\fi

\M{134}When an export section is output, we must push its \PB{\&{text}} on the
output
stack.
\Y\B\&{void} \\{push\_export\_section}(\\{sec})\1\1\6
\&{export\_section} ${}{*}\\{sec};\2\2{}$\6
${}\{{}$\1\6
\&{static} \&{char} \|s[\,]${}\K\.{"\_global"};{}$\6
\&{name\_pointer} \|p${}\K\\{id\_lookup}(\|s,\39\|s+\\{strlen}(\|s),\39%
\T{0});{}$\7
\&{if} ${}(\\{sec}\MG\\{first\_text}){}$\5
${}\{{}$\C{ section not empty? }\1\6
${}\|p\MG\\{equiv}\K{}$(\&{char} ${}{*}){}$ \\{sec}${}\MG\\{first\_text};{}$\6
\\{push\_level}(\|p);\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{135}If we want to have a new \PB{\&{text\_pointer}} for a given
\PB{\&{export\_section}} (e.g.~\PB{\\{shr\_sec}}) and a given \PB{\\{type}}
(e.g.~\PB{\\{declarations}}),
we may call the following function which reserves a new \PB{\&{text}}
variable from the \PB{\\{text\_info}} pool.
\Y\B\&{text\_pointer} ${}\\{new\_text\_ptr}(\\{sec},\39\\{type}){}$\1\1\6
\&{export\_section} ${}{*}\\{sec};{}$\6
\&{int} \\{type};\2\2\6
${}\{{}$\1\6
\&{text\_pointer} \\{txt};\7
\&{if} ${}(\\{text\_ptr}>\\{text\_info\_end}){}$\1\5
\\{overflow}(\.{"text"});\2\6
\&{if} ${}(\\{sec}[\\{type}].\\{last\_text}\E\\{text\_ptr}-\T{1}){}$\1\5
\&{return} ${}\\{text\_ptr}-\T{1}{}$;\C{ we were the last, keep our \PB{%
\&{text}} }\2\6
${}\\{txt}\K\\{text\_ptr}\PP;{}$\6
${}\\{text\_ptr}\MG\\{tok\_start}\K\\{tok\_ptr};{}$\6
${}\\{txt}\MG\\{tok\_start}\K\\{tok\_ptr};{}$\6
${}\\{txt}\MG\\{text\_link}\K\\{section\_flag};{}$\6
\&{if} ${}(\\{sec}[\\{type}].\\{last\_text}\E\NULL){}$\1\5
${}\\{sec}[\\{type}].\\{first\_text}\K\\{txt};{}$\2\6
\&{else}\1\5
${}\\{sec}[\\{type}].\\{last\_text}\MG\\{text\_link}\K\\{txt}-\\{text%
\_info};{}$\2\6
${}\\{sec}[\\{type}].\\{last\_text}\K\\{txt};{}$\6
\&{return} \\{txt};\6
\4${}\}{}$\2\par
\fi

\M{136}\.{mCTANGLE} writes the current section number as comments to
shared and export files in order to inform \.{mCWEAVE} about where
the definitions occurred.
\Y\B\&{void} \\{insert\_section\_comment}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{char} \\{comment}[\T{20}]${},{}$ ${}{*}\\{cp};{}$\7
${}\\{sprintf}(\\{comment},\39\.{"\\03/*Section:\%d*/\\0}\)\.{3\\n"},\39%
\\{section\_count});{}$\6
\&{for} ${}(\\{cp}\K\\{comment};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{cp});{}$\2\6
\4${}\}{}$\2\par
\fi

\M{137}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{process\_exports}(\,);\par
\fi

\M{138}After each section has been read in, all export commands have been
stored in
the array \PB{\\{export\_ref}} which points to the corresponding token position
in \PB{\\{tok\_mem}}. \PB{\\{export\_type}} denotes the type of the export
command
which can be a composed type (e.g.~\&{shared} and \&{export}).
There are \PB{\\{export\_idx}} export commands in the section.

For every command, we have to scan the token list in order to find
out which statement is following. After we know that, we modify the token
list and maybe create new export sections.
\Y\B\F\\{nobreak} \5
\\{break}\par
\B\4\D$\&{nobreak}$ \par
\Y\B\&{void} \\{process\_exports}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{tk};{}$\6
\&{sixteen\_bits} \|i;\6
\&{int} \\{parenthesis}${},{}$ \\{braces};\6
\&{boolean} \\{is\_declaration};\C{ is this a declaration? }\6
\&{boolean} \\{is\_typedef};\C{ is it a \PB{\&{typedef}}? }\6
\&{boolean} \\{is\_inline};\C{ is it an inline function? }\6
\&{boolean} \\{func\_possible};\C{ can it be a function? }\6
\&{eight\_bits} ${}{*}\\{aggregate}{}$;\C{ do we have an aggregate? }\6
\&{int} \\{aggregate\_id};\C{ identifier of aggregate (e.g.~\PB{\\{id\_enum}})
}\6
\&{eight\_bits} ${}{*}\\{aggregate\_label}{}$;\C{ if yes, does it have a label?
}\6
\&{eight\_bits} ${}{*}\\{aggregate\_body},{}$ ${}{*}\\{body\_end}{}$;\C{ if
there, where is its body? }\6
\&{eight\_bits} ${}{*}\\{aggregate\_variable}{}$;\C{ are there variables after
the label or body? }\6
\&{boolean} \\{is\_func\_new\_style};\C{ is it an new style \CEE/ function
head? }\6
\&{boolean} \\{is\_func\_old\_style};\C{ is it an old style function head? }\6
\&{boolean} \\{is\_prototype};\C{ is it a prototype? }\6
\&{boolean} \\{is\_preproc};\C{ is it a preprocessor statement? }\6
\&{boolean} \\{is\_static};\C{ did we see a \PB{\&{static}} keyword? }\6
\&{eight\_bits} ${}{*}\\{func\_arguments}{}$;\C{ points to \.{(} before first
argument }\6
\&{eight\_bits} ${}{*}\\{arg\_end}{}$;\C{ points to \.{)} of arglist }\7
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{export\_idx};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\\{tk}\K\\{export\_ref}[\|i];{}$\6
\&{while} ${}(\\{xisspace}({*}\\{tk})){}$\1\5
${}\\{tk}\PP;{}$\2\6
${}\\{export\_ref}[\|i]\K\\{tk};{}$\6
${}\\{braces}\K\\{parenthesis}\K\T{0};{}$\6
${}\\{is\_declaration}\K\T{0};{}$\6
${}\\{is\_typedef}\K\T{0};{}$\6
${}\\{is\_inline}\K\T{0};{}$\6
${}\\{aggregate}\K\NULL;{}$\6
${}\\{is\_func\_new\_style}\K\T{0};{}$\6
${}\\{is\_func\_old\_style}\K\T{0};{}$\6
${}\\{is\_prototype}\K\T{0};{}$\6
${}\\{is\_preproc}\K\T{0};{}$\6
${}\\{is\_static}\K\T{0};{}$\6
${}\\{func\_arguments}\K\NULL;{}$\6
\X139:Scan the exported statement\X;\6
\&{if} (\\{aggregate})\1\5
\X141:Examine aggregate\X;\2\6
\X143:Store exported statement in export sections\X;\6
\4${}\}{}$\2\6
${}\\{export\_idx}\K\T{0};{}$\6
${}\\{text\_ptr}\MG\\{tok\_start}\K\\{tok\_ptr};{}$\6
\4${}\}{}$\2\par
\fi

\M{139}First of all, we make a global scan over the statement following our
export command. \PB{\\{tk}} points to the first token. If we have seen enough,
we jump to label \PB{\\{done}}.

When running over the token list, we inspect all identifiers searching for
keywords
like \PB{\&{enum}}, \&{class}, \PB{\&{struct}}, \PB{\&{union}}, \PB{\&{extern}}
and \PB{\&{typedef}} which can
indicate the nature of the statement we are looking at.
Additionally, we look for assignments or single `\.{:}' which make us exclude
prototypes and function headers.

After having scanned the token list, we have the following variables set:
\PB{\\{is\_declaration}}, \PB{\\{is\_typedef}}, \PB{\\{is\_inline}}, \PB{%
\\{aggregate}},
\PB{\\{is\_func\_new\_style}}, \PB{\\{is\_func\_old\_style}}, \PB{\\{is%
\_prototype}}, \PB{\\{is\_preproc}}.
\Y\B\4\X139:Scan the exported statement\X${}\E{}$\6
${}\{{}$\1\6
\&{sixteen\_bits} \\{id};\6
\&{boolean} \\{aggregate\_body\_might\_follow}${}\K\T{0}{}$;\C{ next \PB{\.{'%
\{'}} can be start of aggregate body }\7
\&{if} ${}(\\{export\_type}[\|i]\E\\{exp\_export}){}$\5
${}\{{}$\1\6
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}){}$\5
${}\{{}$\1\6
${}\\{id}\K{*}\\{tk}-\T{\~200}\LL\T{8}\OR\\{tk}[\T{1}]{}$;\C{ don't handle
exported import commands }\6
\&{if} ${}(\\{id\_import}\E\\{id}\V\\{id}\E\\{id\_from}){}$\1\5
\&{continue};\2\6
\4${}\}{}$\2\6
\&{if} ${}({*}\\{tk}\E\\{ignore}){}$\1\5
\&{continue};\C{ nor removed import command }\2\6
\4${}\}{}$\2\6
${}\\{func\_possible}\K{-}\T{1}{}$;\C{ yes, but no `(' seen yet }\6
\&{while} ${}(\\{xisspace}({*}\\{tk})){}$\1\5
${}\\{tk}\PP{}$;\C{ allow newline }\2\6
\&{if} ${}({*}\\{tk}\E\.{'\#'}){}$\1\5
${}\\{is\_preproc}\K\T{1};{}$\2\6
\&{while} ${}(\\{tk}<\\{tok\_ptr}){}$\5
${}\{{}$\1\6
\&{switch} ${}({*}\\{tk}\PP){}$\5
${}\{{}$\1\6
\4\&{case} \.{'='}:\6
\&{while} ${}({*}\\{tk}\E\.{'\\n'}){}$\1\5
${}\\{tk}\PP{}$;\C{ allow newline }\2\6
\&{if} ${}({*}\\{tk}\E\.{'\{'}){}$\5
${}\{{}$\C{ \.{\{} after an \.{=} does not terminate statement }\1\6
${}\\{tk}\PP;{}$\6
${}\\{braces}\PP;{}$\6
\4${}\}{}$\2\6
\&{if} (\\{parenthesis})\1\5
\&{break};\C{ maybe \CPLUSPLUS/ default parameter }\2\6
\&{nobreak};\6
\4\&{case} \.{':'}:\6
\&{if} ${}({*}\\{tk}\I\.{':'}){}$\1\5
${}\\{func\_possible}\K\T{0};{}$\2\6
\&{break};\6
\4\&{case} \\{string}:\C{ skip them }\6
\&{case} \\{constant}:\5
\&{do}\5
${}\\{tk}\PP;{}$\5
\&{while} ${}(\\{tk}<\\{tok\_ptr}\W{*}\\{tk}\I\\{string}\W{*}\\{tk}\I%
\\{constant});{}$\6
${}\\{tk}\PP;{}$\6
\&{break};\6
\4\&{case} \.{'('}:\6
\&{if} ${}(\\{func\_possible}<\T{0}){}$\1\5
${}\\{func\_possible}\K\T{1}{}$;\C{ yes, it may be a function }\2\6
${}\\{parenthesis}\PP;{}$\6
${}\\{aggregate\_body\_might\_follow}\K\T{0};{}$\6
\&{break};\6
\4\&{case} \.{')'}:\5
${}\\{parenthesis}\MM{}$;\5
\&{break};\6
\4\&{case} \.{'\}'}:\6
\&{if} (\\{braces})\5
${}\{{}$\1\6
${}\MM\\{braces};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{nobreak};\6
\4\&{case} \.{';'}:\6
\&{if} ${}(\R\\{braces}\W\R\\{parenthesis}){}$\1\5
\&{goto} \\{done};\2\6
${}\\{aggregate\_body\_might\_follow}\K\T{0};{}$\6
\&{break};\6
\4\&{case} \.{'\{'}:\6
\&{if} ${}(\R\\{braces}){}$\1\5
\&{goto} \\{done};\2\6
${}\\{braces}\PP;{}$\6
\&{break};\6
\4\&{default}:\6
\&{if} ${}(\T{\~200}\Z\\{tk}[{-}\T{1}]\W\\{tk}[{-}\T{1}]<\T{\~250}){}$\5
${}\{{}$\C{ identifier }\1\6
${}\\{id}\K\\{tk}[{-}\T{1}]-\T{\~200}\LL\T{8};{}$\6
${}\\{id}\MRL{{\OR}{\K}}{*}\\{tk}\PP;{}$\6
\&{switch} (\\{id})\5
${}\{{}$\1\6
\4\&{case} \\{id\_enum}:\5
\&{case} \\{id\_union}:\5
\&{case} \\{id\_class}:\5
\&{case} \\{id\_struct}:\6
\&{if} ${}(\R\\{aggregate}){}$\5
${}\{{}$\1\6
${}\\{aggregate\_id}\K\\{id};{}$\6
${}\\{aggregate}\K\\{tk};{}$\6
\4${}\}{}$\2\6
${}\\{aggregate\_body\_might\_follow}\K\T{1};{}$\6
\&{break};\6
\4\&{case} \\{id\_extern}:\5
${}\\{is\_declaration}\K\T{1}{}$;\5
\&{break};\6
\4\&{case} \\{id\_typedef}:\5
${}\\{is\_typedef}\K\T{1}{}$;\5
\&{break};\6
\4\&{case} \\{id\_inline}:\5
${}\\{is\_inline}\K\T{1}{}$;\5
\&{break};\6
\4\&{case} \\{id\_static}:\5
${}\\{is\_static}\K\T{1}{}$;\5
\&{break};\6
\4${}\}{}$\2\6
\&{while} ${}({*}\\{tk}\E\.{'\\n'}){}$\1\5
${}\\{tk}\PP{}$;\C{ allow newline }\2\6
\&{if} ${}({*}\\{tk}\E\.{'\{'}\W\\{aggregate\_body\_might\_follow}){}$\5
${}\{{}$\1\6
${}\\{braces}\PP{}$;\C{ `\.{\{}' following an identifier introduces aggregate
body }\6
${}\\{tk}\PP;{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{tk}[{-}\T{1}]\E\T{\~320}\W{*}\\{tk}\E\T{0}){}$\1\5
${}\\{tk}\MRL{+{\K}}\T{5}{}$;\C{ skip \&{\#line} info }\2\6
\&{else} \&{if} ${}(\\{tk}[{-}\T{1}]\G\T{\~250}){}$\1\5
${}\\{tk}\PP;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4\\{done}:\6
\&{if} ${}(\\{func\_possible}<\T{0}){}$\1\5
${}\\{func\_possible}\K\T{0}{}$;\C{ never saw a `(' }\2\6
\&{else}\1\5
\X140:Is it a function or prototype?\X;\2\6
\4${}\}{}$\2\par
\U138.\fi

\M{140}If \PB{$\\{func\_possible}\I\T{0}$} the statement following our export
command may be a function head or a prototype.
But it may also be a variable definition, so we should
examine it in more detail.

In order to be a function, the last \.{(} must be preceded by an
identifier. The keyword \PB{\\{operator}} also implies a new style function.
If the corresponding \.{)} is followed by an identifier,
we have an old-style function head. If we see a \.{\{} behind it, we
have a new-style function head. In case of a \.{,} or a \.{;} we can
treat our statement as a prototype.
According to what we find, we set the variables \PB{\\{is\_func\_new\_style}},
\PB{\\{is\_func\_old\_style}} and \PB{\\{is\_prototype}}.

These are the basic rules for our inspection, but there are no rules
without exceptions. If we only have an identifier list in the argument
list or if there is no arglist at all, we have an old style function
definition.

On the other hand, if the argument list only contains \.{void}, we have
a new style function head.
\Y\B\4\X140:Is it a function or prototype?\X${}\E{}$\6
${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{tp},{}$ \|c;\6
\&{int} \\{parenthesis}${}\K\T{0};{}$\6
\&{boolean} \\{can\_be\_new\_style};\C{ can it possibly be a new style function
head? }\7
${}\\{func\_arguments}\K\NULL;{}$\6
${}\\{tp}\K\\{export\_ref}[\|i];{}$\6
\&{while} ${}(\\{tp}\Z\\{tk}){}$\5
${}\{{}$\1\6
${}\|c\K{*}\\{tp}\PP;{}$\6
\&{if} ${}(\|c\G\T{\~200}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|c\E\T{\~320}\W{*}\\{tp}\E\T{0}){}$\1\5
${}\\{tp}\MRL{+{\K}}\T{4}{}$;\C{ skip \&{\#line} info }\2\6
${}\\{tp}\PP;{}$\6
\&{if} ${}(\|c<\T{\~250}){}$\5
${}\{{}$\C{ identifier }\1\6
${}\\{id}\K\|c-\T{\~200}\LL\T{8}\OR\\{tp}[{-}\T{1}];{}$\6
\&{if} ${}(\\{id}\E\\{id\_operator}){}$\5
${}\{{}$\1\6
${}\\{arg\_end}\K\\{tk}-\T{1};{}$\6
\&{if} ${}({*}\\{arg\_end}\E\.{'\{'}){}$\1\5
${}\\{arg\_end}\MM;{}$\2\6
${}\\{is\_func\_new\_style}\K\T{1};{}$\6
\&{break};\6
\4${}\}{}$\2\6
\&{if} ${}({*}\\{tp}\E\.{'('}\W\R\\{parenthesis}){}$\5
${}\{{}$\1\6
${}\\{func\_arguments}\K\\{tp};{}$\6
${}\\{can\_be\_new\_style}\K\T{0};{}$\6
${}\\{tp}\PP;{}$\6
${}\\{parenthesis}\K\T{1};{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{func\_arguments}\W\T{\~200}\Z{*}\\{tp}\W{*}\\{tp}<\T{%
\~250}){}$\1\5
${}\\{can\_be\_new\_style}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\|c\E\.{'('}){}$\5
${}\{{}$\1\6
${}\\{parenthesis}\PP;{}$\6
${}\\{func\_arguments}\K\NULL;{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\|c\E\.{')'}){}$\5
${}\{{}$\1\6
${}\MM\\{parenthesis};{}$\6
${}\\{arg\_end}\K\\{tp}-\T{1};{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{func\_arguments}\W\\{parenthesis}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|c\I\.{','}){}$\1\5
${}\\{can\_be\_new\_style}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{func\_arguments}\W\\{parenthesis}\E\T{0}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{arg\_end}-\\{func\_arguments}\E\T{3}\W\T{\~200}\Z\\{func%
\_arguments}[\T{1}]\W\\{func\_arguments}[\T{1}]<\T{\~250}){}$\5
${}\{{}$\C{ test for \&{void} as only parameter }\1\6
\&{int} \|a${}\K\\{func\_arguments}[\T{1}]-\T{\~200}\LL\T{8}\OR\\{func%
\_arguments}[\T{2}];{}$\7
\&{if} ${}(\|a\E\\{id\_void}){}$\1\5
${}\\{can\_be\_new\_style}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
${}\\{tp}\K\\{arg\_end}+\T{1};{}$\6
\&{while} ${}(\\{isspace}({*}\\{tp})){}$\1\5
${}\\{tp}\PP;{}$\2\6
\&{if} ${}({*}\\{tp}\E\.{'\{'}){}$\5
${}\{{}$\1\6
\&{if} (\\{can\_be\_new\_style})\1\5
${}\\{is\_func\_new\_style}\K\T{1}{}$;\C{ in most cases }\2\6
\&{else}\1\5
${}\\{is\_func\_old\_style}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\T{\~200}\Z{*}\\{tp}\W{*}\\{tp}<\T{\~250}{}$)\C{ identifier
}\1\6
${}\\{is\_func\_old\_style}\K\T{1};{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{','}\V{*}\\{tp}\E\.{';'}){}$\1\5
${}\\{is\_prototype}\K\T{1};{}$\2\6
\&{else}\1\5
${}\\{func\_arguments}\K\NULL;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U139.\fi

\M{141}If \PB{$\\{aggregate}\I\NULL$} we know,
that we have an aggregate in our statement, but we
don't know exactly what kind. So we examine it in order to find out
if it has a label, a body or if there are variables defined.

All the results are then stored in \PB{\\{aggregate\_label}},
\PB{\\{aggregate\_body}}, \PB{\\{body\_end}} and \PB{\\{aggregate\_variable}}.
\Y\B\4\X141:Examine aggregate\X${}\E{}$\6
${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{tp}\K\\{aggregate};{}$\7
${}\\{aggregate\_label}\K\NULL;{}$\6
${}\\{aggregate\_body}\K\NULL;{}$\6
${}\\{aggregate\_variable}\K\NULL;{}$\6
\&{while} ${}({*}\\{tp}\E\.{'\\n'}){}$\1\5
${}\\{tp}\PP;{}$\2\6
\&{if} ${}(\T{\~200}\Z{*}\\{tp}\W{*}\\{tp}<\T{\~250}){}$\5
${}\{{}$\C{ identifier following }\1\6
${}\\{aggregate\_label}\K\\{tp};{}$\6
${}\\{tp}\MRL{+{\K}}\T{2};{}$\6
\&{while} ${}({*}\\{tp}\E\.{'\\n'}){}$\1\5
${}\\{tp}\PP;{}$\2\6
\&{if} ${}({*}\\{tp}\E\.{'\{'}\V{*}\\{tp}\E\.{':'}\W\\{tp}[\T{1}]\I\.{':'}){}$%
\1\5
${}\\{aggregate\_body}\K\\{tp};{}$\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{'\{'}){}$\1\5
${}\\{aggregate\_body}\K\\{tp};{}$\2\6
\&{if} (\\{aggregate\_body})\5
${}\{{}$\1\6
${}\\{body\_end}\K\\{aggregate\_body};{}$\6
\X142:\PB{\\{body\_end}} points to `\.{\{}', find corresponding `\.{\}}'\X;\6
\4${}\}{}$\2\6
\&{else} \&{if} (\\{aggregate\_label})\1\5
${}\\{body\_end}\K\\{aggregate\_label}+\T{1};{}$\2\6
\&{else}\1\5
${}\\{body\_end}\K\NULL{}$;\C{ neither body nor label }\2\6
\&{if} (\\{body\_end})\5
${}\{{}$\1\6
${}\\{tp}\K\\{body\_end}+\T{1};{}$\6
\&{while} ${}({*}\\{tp}\E\.{'\\n'}){}$\1\5
${}\\{tp}\PP;{}$\2\6
\&{if} ${}({*}\\{tp}\I\.{';'}){}$\1\5
${}\\{aggregate\_variable}\K\\{tp};{}$\2\6
\4${}\}{}$\2\6
${}\\{aggregate}\MRL{-{\K}}\T{2}{}$;\C{ point to \PB{\&{struct}} or the like }\6
\4${}\}{}$\2\par
\U138.\fi

\M{142}\PB{\\{body\_end}} points to an opening brace or the \.{':'} of a class
definition and
should be incremented until we find the corresponding
closing brace. But don't count braces that appear in strings.
\Y\B\4\X142:\PB{\\{body\_end}} points to `\.{\{}', find corresponding `\.{\}}'%
\X${}\E{}$\6
${}\{{}$\1\6
\&{boolean} \\{in\_verb}${}\K\T{0}{}$;\C{ are we in verbatim mode? }\7
${}\\{braces}\K\T{0};{}$\6
${}\\{body\_end}\MM;{}$\6
\&{while} ${}(\PP\\{body\_end}<\\{tok\_ptr}){}$\5
${}\{{}$\1\6
\&{switch} ${}({*}\\{body\_end}){}$\5
${}\{{}$\1\6
\4\&{case} \.{'\{'}:\6
\&{if} ${}(\R\\{in\_verb}){}$\1\5
${}\\{braces}\PP;{}$\2\6
\&{break};\6
\4\&{case} \.{'\}'}:\6
\&{if} ${}(\R\\{in\_verb}\W\MM\\{braces}\E\T{0}){}$\1\5
\&{goto} \\{found};\2\6
\&{break};\6
\4\&{case} \\{string}:\5
\&{case} \\{constant}:\5
${}\\{in\_verb}\K\R\\{in\_verb};{}$\6
\&{break};\6
\4\&{default}:\6
\&{if} ${}({*}\\{body\_end}\E\T{\~320}\W\\{body\_end}[\T{1}]\E\T{0}){}$\1\5
${}\\{body\_end}\MRL{+{\K}}\T{5}{}$;\C{ skip \&{\#line} info }\2\6
\&{else} \&{if} ${}({*}\\{body\_end}\G\T{\~200}){}$\1\5
${}\\{body\_end}\PP{}$;\C{ skip identifier }\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{aggregate\_body}\K\NULL;{}$\6
\&{if} (\\{braces})\1\5
\\{err\_print}(\.{"!\ Cannot\ find\ corre}\)\.{sponding\ \}\ for\ aggre}\)%
\.{gate"});\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Class\ derivation\ }\)\.{without\ \{\ body\ \};"});\2\6
\4\\{found}:\5
;\6
\4${}\}{}$\2\par
\U141.\fi

\M{143}We now have analyzed our statement, now we can store it in the
export sections and we can modify our original token list so that
not necessarily everything will remain in the \CEE/ output file.

Which export command(s) we handle is stored in \PB{\\{export\_type}[\|i]}.
This determines where to write the exported statement.
\Y\B\4\X143:Store exported statement in export sections\X${}\E{}$\6
${}\{{}$\1\6
\&{sixteen\_bits} \\{type}${}\K\\{export\_type}[\|i];{}$\6
\&{export\_section} ${}{*}\\{sec};{}$\6
\&{eight\_bits} ${}{*}\\{tp};{}$\7
${}\\{also\_to\_exp\_sec}\K\T{0}{}$;\C{ see below }\6
\&{if} ${}(\\{type}\E\\{exp\_export}){}$\5
${}\{{}$\1\6
${}\\{sec}\K\\{exp\_sec}{}$;\C{ we only write to export file }\6
${}\\{modify\_original\_token\_list}\K\T{0}{}$;\C{ keep original token list
unchanged }\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{type}\AND\\{exp\_export}){}$\1\5
${}\\{also\_to\_exp\_sec}\K\T{1}{}$;\C{ to export file and another one }\2\6
\&{if} ${}(\\{type}\AND\\{exp\_global}){}$\1\5
${}\\{sec}\K\\{glb\_sec};{}$\2\6
\&{else} \&{if} ${}(\\{type}\AND\\{exp\_shared}){}$\1\5
${}\\{sec}\K\\{shr\_sec};{}$\2\6
${}\\{modify\_original\_token\_list}\K\T{1}{}$;\C{ modify original token list }%
\6
\4${}\}{}$\2\6
\&{if} ${}(\\{aggregate}\W\\{aggregate\_id}\E\\{id\_class}\W\\{aggregate%
\_label}){}$\1\5
\X146:Create forward reference for \&{class}\X\2\6
\&{if} (\\{is\_preproc})\5
${}\{{}$\1\6
\X147:Store preprocessor command in \PB{\\{sec}}\X;\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} (\\{is\_typedef})\5
${}\{{}$\1\6
\X148:Store typedef in \PB{\\{sec}}\X;\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{aggregate}\W(\\{aggregate\_label}\V\\{aggregate\_id}\E\\{id%
\_enum}\W\R\\{aggregate\_variable})\W\\{aggregate\_body}){}$\5
${}\{{}$\1\6
\X149:Store aggregate definition in \PB{\\{sec}}\X;\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X150:Remove aggregate body\X;\2\6
\&{if} ${}(\R\\{aggregate\_variable}){}$\5
${}\{{}$\C{ nothing behind body, remove whole statement }\1\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} (\\{is\_declaration})\5
${}\{{}$\1\6
\X151:Store declaration in \PB{\\{sec}}\X;\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{is\_inline}\W\\{tk}[{-}\T{1}]\E\.{'\{'}){}$\5
${}\{{}$\1\6
\X152:Move \PB{\&{inline}} function including function body to \PB{\\{sec}}\X;\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} (\\{is\_func\_old\_style})\5
${}\{{}$\1\6
\X153:Generate prototype from old style function head and store it in \PB{%
\\{sec}}\X;\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} (\\{is\_func\_new\_style})\5
${}\{{}$\1\6
\X159:Generate prototype from new style function head and store it in \PB{%
\\{sec}}\X;\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} (\\{is\_prototype})\5
${}\{{}$\1\6
\X151:Store declaration in \PB{\\{sec}}\X;\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\&{if} ${}(\R\\{is\_static}{}$)\C{ assume variable definition }\1\6
\X160:Copy variable to \PB{\\{sec}}, preceded by \PB{\&{extern}}, without
assignments\X;\2\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X161:Move variable to \PB{\\{var\_sec}}\X;\2\6
\4\\{stored}:\5
${}\\{text\_ptr}\MG\\{tok\_start}\K\\{tok\_ptr}{}$;\C{ \PB{\&{text}} ends here
}\6
\4${}\}{}$\2\par
\U138.\fi

\M{144}We have already seen the function \PB{\\{new\_text\_ptr}} which reserves
a new \PB{\&{text\_pointer}} for the given export section and type.
Here we want to define a macro that automatically calls
\PB{\\{new\_text\_ptr}} with the argument \PB{\\{exp\_sec}} if the boolean
variable \PB{\\{also\_to\_exp\_sec}} is set.
So, we can store everything that goes to, say, the \PB{\\{global}} section
also to the \PB{\\{export}} section without additional effort.
\Y\B\4\D$\\{x\_new\_text\_ptr}(\\{sec},\\{type})$ \6
${}\{{}$\1\6
\&{if} (\\{also\_to\_exp\_sec})\1\5
${}\\{new\_text\_ptr}(\\{exp\_sec},\39\\{type});{}$\2\6
${}\\{new\_text\_ptr}(\\{sec},\39\\{type});{}$\6
\\{insert\_section\_comment}(\,);\6
\4${}\}{}$\2\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{boolean} \\{also\_to\_exp\_sec};\6
\&{boolean} \\{modify\_original\_token\_list};\par
\fi

\M{145}Sometimes we have to remove the statement from the original token list
so that it does not appear in the \CEE/ file. This is done by overwriting
it in \PB{\\{tok\_mem}} with the token \PB{\\{ignore}}.
\Y\B\4\X145:Remove statement\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\1\6
\&{if} ${}({*}\\{tp}\I\.{'\\n'}){}$\1\5
${}{*}\\{tp}\K\\{ignore};{}$\2\2\6
\4${}\}{}$\2\par
\Us143, 146, 152\ETs161.\fi

\M{146}Every time we encounter a new class definition, we output a
forward declaration to the \PB{\\{forward\_types}} export section, thus
making it easy to reorder the definition of the classes without
taking in account the dependencies between them.
\Y\B\4\X146:Create forward reference for \&{class}\X${}\E{}$\6
${}\{{}$\1\6
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{forward\_types});{}$\6
\\{remember\_export\_line}(\|i);\6
\&{for} ${}(\\{tp}\K\\{aggregate};{}$ ${}\\{tp}<\\{aggregate\_label}+\T{2};{}$
${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\6
\&{if} ${}({*}\\{tp}\E\.{';'}){}$\5
${}\{{}$\C{ it is already only a forward declaration }\1\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\&{goto} \\{stored};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U143.\fi

\M{147}
\Y\B\4\X147:Store preprocessor command in \PB{\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{types});{}$\6
\\{remember\_export\_line}(\|i);\C{ put \&{\#line} info into token memory }\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\5
${}\{{}$\1\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\&{if} ${}({*}\\{tp}\E\.{'\\n'}\W\\{tp}[{-}\T{1}]\I\.{'\\\\'}){}$\5
${}\{{}$\1\6
${}\\{tk}\K\\{tp}+\T{1}{}$;\C{ preprocessor command ends here (for removing) }\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{tp}\E\\{tk}){}$\1\5
\\{app\_repl}(\.{'\\n'});\2\6
\4${}\}{}$\2\par
\U143.\fi

\M{148}Simply copy \PB{\&{typedef}} statement to \PB{\\{sec}}. The statement
terminates
at \PB{\\{tk}}.
\Y\B\4\X148:Store typedef in \PB{\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{types}){}$;\C{ new \PB{\&{text%
\_pointer}} }\6
\\{remember\_export\_line}(\|i);\C{ insert line info from \PB{\\{export\_line}[%
\|i]} }\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\par
\U143.\fi

\M{149}If an aggregate definition occurs, we extract the aggregate definition
and store it to the \PB{\\{types}} section.
But if the aggregate has no label, we will have to precede it with \PB{$\#$ %
\&{ifndef}}
so that the chapter it is defined in does not see it.
This will be done in \PB{$\X160:Copy variable to \PB{\\{sec}}, preceded by \PB{%
\&{extern}}, without assignments\X$}, where the variable declaration
will be copied to the shared/export file.
\Y\B\4\X149:Store aggregate definition in \PB{\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{aggregate\_id}\E\\{id\_enum}\?\\{forward%
\_types}:\\{types});{}$\6
\\{remember\_export\_line}(\|i);\6
\&{for} ${}(\\{tp}\K\\{aggregate};{}$ ${}\\{tp}\Z\\{body\_end};{}$ ${}\\{tp}%
\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\par
\U143.\fi

\M{150}If we have stored the aggregate definition to the \PB{\\{types}} section
we don't want to repeat the body in the \CEE/ file and therefore
remove it.
\Y\B\4\X150:Remove aggregate body\X${}\E{}$\6
\&{for} ${}(\\{tp}\K\\{aggregate\_body};{}$ ${}\\{tp}\Z\\{body\_end};{}$ ${}%
\\{tp}\PP){}$\1\6
\&{if} ${}({*}\\{tp}\I\.{'\\n'}){}$\1\5
${}{*}\\{tp}\K\\{ignore}{}$;\2\2\par
\U143.\fi

\M{151}Declarations are simply inserted into the \PB{\\{declarations}} section.
\Y\B\4\X151:Store declaration in \PB{\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{declarations});{}$\6
\\{remember\_export\_line}(\|i);\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\par
\U143.\fi

\M{152}Inline functions must be treated differently from ordinary functions,
since we do not want to have a prototype in the header, but the whole function
including the function body.
\Y\B\4\X152:Move \PB{\&{inline}} function including function body to \PB{%
\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \\{braces};\7
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{declarations});{}$\6
\\{remember\_export\_line}(\|i);\6
${}\\{braces}\K\T{0};{}$\6
\&{for} ${}(\\{tp}\K\\{tk}-\T{1};{}$ ${}\\{tp}<\\{tok\_ptr};{}$ ${}\\{tp}%
\PP){}$\5
${}\{{}$\C{ find end of function body }\1\6
\&{switch} ${}({*}\\{tp}\PP){}$\5
${}\{{}$\1\6
\4\&{case} \\{string}:\5
\&{case} \\{constant}:\5
\&{do}\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tp}\E\\{string}\V{*}\\{tp}\E\\{constant}){}$\5
${}\{{}$\1\6
${}\\{tp}\PP;{}$\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\5
\&{while} ${}(\PP\\{tp}<\\{tok\_ptr});{}$\6
\&{goto} \\{have\_it};\6
\4\&{case} \.{'\{'}:\5
${}\\{braces}\PP;{}$\6
\&{break};\6
\4\&{case} \.{'\}'}:\5
${}\\{braces}\MM;{}$\6
\&{if} ${}(\R\\{braces}){}$\1\5
\&{goto} \\{have\_it};\2\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4\\{have\_it}:\5
${}\\{tk}\K\\{tp}{}$;\C{ here is the new end, in case we want to remove the
function }\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{'\\n'});\6
\&{if} (\\{modify\_original\_token\_list})\1\5
\X145:Remove statement\X;\2\6
\4${}\}{}$\2\par
\U143.\fi

\M{153}This is difficult. We have a old style function head and want to
generate a prototype for it. So, we have to scan the argument declarations
following the function head in order to find out which types the arguments
have.

There are two cases which are rather easy to handle.
If the user wants only Kernighan \AM\ Ritchie prototypes (by giving
the {\tt+k} flag), i.e.~prototypes with empty arguments,
we simply omit the argument list and have a prototype.
The other simple case is if we have an empty arglist.
All other cases require a closer examination of the argument declarations.

Remember, that in old style function heads, the arglist is only an
identifier list. So, first of all, we store all argument names (their
identifiers) in the \PB{\\{argument}} array.
\Y\B\4\D$\\{max\_args}$ \5
\T{32}\C{ maximum of arguments in arglist }\par
\Y\B\4\X153:Generate prototype from old style function head and store it in %
\PB{\\{sec}}\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \\{num\_args}${},{}$ \|a${},{}$ \|j;\6
\&{eight\_bits} ${}{*}\\{cur\_type\_start}{}$;\C{ points to first token of
current declaration }\6
\&{eight\_bits} ${}{*}\\{cur\_type\_end}{}$;\C{ points to last token+1 of type
part of current declaration }\6
\&{eight\_bits} ${}{*}\\{cur\_variable\_start}{}$;\C{ points to start of
variable }\6
\&{sixteen\_bits} \\{argument}[\\{max\_args}];\6
\&{eight\_bits} ${}{*}\\{type\_start}[\\{max\_args}],{}$ ${}{*}\\{type\_end}[%
\\{max\_args}];{}$\6
\&{eight\_bits} ${}{*}\\{variable\_start}[\\{max\_args}];{}$\7
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{declarations});{}$\6
\\{remember\_export\_line}(\|i);\6
\X154:If K \AM\ R style, simply omit arguments\X;\6
\X155:Check for empty arglist, \PB{\&{goto} \\{proto\_generated}} if found\X;\6
\X156:Store the argument identifiers in \PB{\\{argument}}\X;\6
${}\\{cur\_type\_start}\K\\{arg\_end}+\T{1};{}$\6
\&{while} ${}(\\{xisspace}({*}\\{cur\_type\_start})){}$\1\5
${}\\{cur\_type\_start}\PP;{}$\2\6
${}\\{cur\_type\_end}\K\\{cur\_variable\_start}\K\NULL;{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{num\_args};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\\{type\_start}[\|j]\K\NULL{}$;\C{ where does type for argument number $j$
start }\6
${}\\{type\_end}[\|j]\K\NULL;{}$\6
${}\\{variable\_start}[\|j]\K\NULL;{}$\6
\4${}\}{}$\2\6
\X157:Find declaration for each argument\X;\6
\X158:Output the prototype for our old style function\X;\6
\4\\{proto\_generated}:\5
;\6
\4${}\}{}$\2\par
\U143.\fi

\M{154}If we have Kernighan \AM~Ritchie \CEE/, then we just omit the arguments
and have a prototype.
\Y\B\4\X154:If K \AM\ R style, simply omit arguments\X${}\E{}$\6
\&{if} (\\{flags}[\.{'k'}])\5
${}\{{}$\1\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}\Z\\{func\_arguments};{}$
${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{')'});\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\6
\&{goto} \\{proto\_generated};\6
\4${}\}{}$\2\par
\U153.\fi

\M{155}If we have a old style function head with an empty arglist
(e.g.~\PB{\&{void} \\{func}(\,)}), we simply insert a \PB{\&{void}} between the
opening and
closing parenthesis.
\Y\B\4\X155:Check for empty arglist, \PB{\&{goto} \\{proto\_generated}} if
found\X${}\E{}$\6
\&{if} ${}(\\{func\_arguments}\E\\{arg\_end}-\T{1}){}$\5
${}\{{}$\C{ empty arglist, simply insert \PB{\&{void}} }\1\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}\Z\\{func\_arguments};{}$
${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
${}\\{app\_repl}(\T{\~200}+(\\{id\_void}/\T{\~400}));{}$\6
${}\\{app\_repl}(\\{id\_void}\AND\T{\~377});{}$\6
\&{for} ( ; ${}\\{tp}\Z\\{arg\_end};{}$ ${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\6
\&{goto} \\{proto\_generated};\6
\4${}\}{}$\2\par
\U153.\fi

\M{156}We go through the argument list and store each identifier in
the array \PB{\\{argument}}. \PB{\\{num\_args}} will contain the number of
arguments found.
\Y\B\4\X156:Store the argument identifiers in \PB{\\{argument}}\X${}\E{}$\6
$\\{num\_args}\K\T{0};{}$\6
\&{for} ${}(\\{tp}\K\\{func\_arguments}+\T{1};{}$ ${}\\{tp}<\\{arg\_end};{}$
${}\\{tp}\PP){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tp}\G\T{\~200}\W{*}\\{tp}<\T{\~250}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{num\_args}\E\\{max\_args}){}$\1\5
\\{overflow}(\.{"function\ arguments"});\2\6
${}\\{argument}[\\{num\_args}]\K{*}\\{tp}\LL\T{8};{}$\6
${}\\{argument}[\\{num\_args}]\MRL{+{\K}}{*}\PP\\{tp};{}$\6
${}\\{num\_args}\PP;{}$\6
${}\PP\\{tp};{}$\6
\&{if} ${}({*}\\{tp}\I\.{','}){}$\1\5
\&{break};\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{tp}<\\{arg\_end}){}$\5
${}\{{}$\1\6
${}\\{printf}(\.{"!\ Illegal\ old\ style}\)\.{\ function\ head\ (file}\)\.{\ %
\\"\%s\\",\ l.\ \%d)\\n"},\39\\{export\_file\_name}[\|i],\39\\{export\_line}[%
\|i]);{}$\6
\\{mark\_error};\6
\&{goto} \\{proto\_generated};\6
\4${}\}{}$\2\par
\U153.\fi

\M{157}We now have to match the argument names \PB{\\{argument}[\,]} and the
declarations after the function head. Every time we find the
matching declaration for argument $j$, set the corresponding
array entries \PB{\\{type\_start}[\|j]}, \PB{\\{type\_end}[\|j]} and \PB{%
\\{variable\_start}[\|j]}
to the start and end of the type and the start of the variable
in the declaration.

Fortunately, types must not have the same name as a variable, only
aggregate labels may have the same name as a variable.
So we always skip aggregate labels and compare the rest of the identifiers
with our arguments. This way we find out, which argument belongs to which
declaration.

The variables \PB{\\{cur\_type\_start}} and \PB{\\{cur\_type\_end}} always
contain the
start and end of the type part of the declaration we are dealing with.
\PB{\\{cur\_variable\_start}} points to the start of the variable part,
i.e.~the
part which is specific to the variable itself. This includes the pointer
marker \.{*}, since \PB{\&{int} ${}{*}\|a,{}$ \|b;} means that only \PB{\|a}
should be a pointer.
\Y\B\4\X157:Find declaration for each argument\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\\{tp}\K\\{cur\_type\_start};{}$ ${}\\{tp}<\\{tok\_ptr};{}$ ${}%
\\{tp}\PP){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tp}\G\T{\~200}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tp}<\T{\~250}){}$\5
${}\{{}$\C{ identifier found }\1\6
${}\|a\K{*}\\{tp}\LL\T{8};{}$\6
${}\|a\MRL{+{\K}}{*}\PP\\{tp};{}$\6
\&{if} ${}(\|a\G\\{id\_enum}\W\|a\Z\\{id\_struct}){}$\5
${}\{{}$\C{ aggregate }\1\6
\&{if} ${}(\T{\~200}\Z\\{tp}[\T{1}]\W\\{tp}[\T{1}]<\T{\~250}){}$\1\5
${}\\{tp}\MRL{+{\K}}\T{2}{}$;\C{ skip label }\2\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\C{ try to match with arguments }\1\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{num\_args};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\|a\E\\{argument}[\|j]){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{cur\_type\_end}){}$\1\5
${}\\{cur\_variable\_start}\K\\{cur\_type\_end}\K\\{tp}-\T{1};{}$\2\6
${}\\{type\_start}[\|j]\K\\{cur\_type\_start};{}$\6
${}\\{type\_end}[\|j]\K\\{cur\_type\_end};{}$\6
${}\\{variable\_start}[\|j]\K\\{cur\_variable\_start};{}$\6
\4${}\}{}$\2\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{tp}[\T{1}]\E\.{'\{'}){}$\5
${}\{{}$\C{ skip aggregate body }\1\6
\&{int} \\{braces}${}\K\T{0};{}$\7
\&{do}\5
\&{if} ${}({*}\PP\\{tp}\E\.{'\{'}){}$\1\5
${}\\{braces}\PP;{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{'\}'}){}$\1\5
${}\\{braces}\MM;{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\G\T{\~200}){}$\1\5
${}\\{tp}\PP;{}$\2\5
\&{while} ${}(\\{braces}\W\\{tp}<\\{tok\_ptr});{}$\6
\&{if} (\\{braces})\5
${}\{{}$\1\6
\\{err\_print}(\.{"!\ Can't\ find\ closin}\)\.{g\ `\}'\ of\ aggregate\ b}\)%
\.{ody"});\6
\&{goto} \\{proto\_generated};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{tp}\PP{}$;\C{ skip second byte of 2-byte token }\2\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{';'}){}$\5
${}\{{}$\C{ current type ends, new type begins }\1\6
${}\\{cur\_type\_start}\K\\{tp}+\T{1};{}$\6
\&{while} ${}(\\{xisspace}({*}\\{cur\_type\_start})){}$\1\5
${}\\{cur\_type\_start}\PP;{}$\2\6
${}\\{cur\_type\_end}\K\NULL{}$;\C{ end not known yet }\6
${}\\{cur\_variable\_start}\K\NULL;{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{','}){}$\1\5
${}\\{cur\_variable\_start}\K\\{tp}+\T{1}{}$;\C{ new variable, same type }\2\6
\&{else} \&{if} ${}({*}\\{tp}\E\.{'\{'}){}$\1\5
\&{break};\C{ start of function body, done }\2\6
\&{else} \&{if} ${}(\R\\{cur\_type\_end}\W\R\\{isspace}({*}\\{tp}){}$)\C{ end
of current type }\1\6
${}\\{cur\_type\_end}\K\\{cur\_variable\_start}\K\\{tp};{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U153.\fi

\M{158}When we finally know which argument has which type, we can output
the prototype. For argument $j$, \PB{\\{type\_start}[\|j]} and \PB{\\{type%
\_end}[\|j]} give
the start and end position in the token list for its type.
The variable name itself can be found at \PB{\\{variable\_start}[\|j]}, ending
with a '\.{,}' or '\.{;}'.

All variables that have \PB{$\\{type\_start}[\|j]\E\NULL$} default to \PB{%
\&{int}}, since
they have been omitted in the declaration list.
\Y\B\4\X158:Output the prototype for our old style function\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}\Z\\{func\_arguments};{}$
${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{num\_args};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{type\_start}[\|j]){}$\5
${}\{{}$\C{ argument defaults to \PB{\&{int}} }\1\6
${}\\{app\_repl}((\\{id\_int}\GG\T{8})+\T{\~200});{}$\6
${}\\{app\_repl}(\\{id\_int}\AND\T{\~377});{}$\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{for} ${}(\\{tp}\K\\{type\_start}[\|j];{}$ ${}\\{tp}<\\{type\_end}[\|j];{}$
${}\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\&{for} ${}(\\{tp}\K\\{variable\_start}[\|j];{}$ ${}{*}\\{tp}\I\.{','}\W{*}%
\\{tp}\I\.{';'}\W\\{tp}<\\{tok\_ptr};{}$ ${}\\{tp}\PP){}$\5
${}\{{}$\1\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\&{if} ${}({*}\\{tp}\G\T{\~200}){}$\5
${}\{{}$\1\6
${}\PP\\{tp};{}$\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|j\I\\{num\_args}-\T{1}){}$\1\5
\\{app\_repl}(\.{','});\2\6
\4${}\}{}$\2\6
\\{app\_repl}(\.{')'});\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\par
\U153.\fi

\M{159}Generating a prototype from a new style function head is rather simple.
Just append a \.{;} after the parameter list and you are done.
\Y\B\4\X159:Generate prototype from new style function head and store it in %
\PB{\\{sec}}\X${}\E{}$\6
$\\{x\_new\_text\_ptr}(\\{sec},\39\\{declarations});{}$\6
\\{remember\_export\_line}(\|i);\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}\Z\\{arg\_end};{}$ ${}%
\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\\{app\_repl}(\.{';'});\6
\\{app\_repl}(\.{'\\n'});\par
\U143.\fi

\M{160}Variables are copied to \PB{\\{declarations}}, but without any
assignments.
They get an \PB{\&{extern}} in front of the actual definition in order to
make them declarations.
\Y\B\4\X160:Copy variable to \PB{\\{sec}}, preceded by \PB{\&{extern}}, without
assignments\X${}\E{}$\6
${}\{{}$\1\6
\&{boolean} \\{copy\_on}${}\K\T{1};{}$\6
\&{eight\_bits} \|c;\6
\&{boolean} \\{if\_ndef};\7
${}\\{x\_new\_text\_ptr}(\\{sec},\39\\{declarations});{}$\6
\\{remember\_export\_line}(\|i);\6
${}\\{if\_ndef}\K\\{aggregate}\W\\{aggregate\_body}\W\\{aggregate\_label}\E%
\NULL;{}$\6
\&{if} (\\{if\_ndef})\5
${}\{{}$\1\6
\\{app\_repl}(\.{'\#'});\6
${}\\{app\_repl}((\\{id\_ifndef}\GG\T{8})+\T{\~200});{}$\6
${}\\{app\_repl}(\\{id\_ifndef}\AND\T{\~377});{}$\6
${}\\{app\_repl}((\\{id\_file\_name\_constant}\GG\T{8})+\T{\~200});{}$\6
${}\\{app\_repl}(\\{id\_file\_name\_constant}\AND\T{\~377});{}$\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\6
${}\\{app\_repl}((\\{id\_extern}\GG\T{8})+\T{\~200}){}$;\C{ insert \PB{%
\&{extern}} into token list }\6
${}\\{app\_repl}(\\{id\_extern}\AND\T{\~377});{}$\6
${}\\{braces}\K\T{0};{}$\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\5
${}\{{}$\1\6
\&{switch} ${}(\|c\K{*}\\{tp}){}$\5
${}\{{}$\1\6
\4\&{case} \\{ignore}:\C{ don't copy \PB{\\{ignore}} tokens }\6
\&{break};\6
\4\&{case} \.{'\{'}:\5
${}\\{braces}\PP;{}$\6
\&{break};\6
\4\&{case} \.{'\}'}:\5
${}\\{braces}\MM;{}$\6
\&{break};\6
\4\&{case} \.{'='}:\5
${}\\{copy\_on}\K\T{0}{}$;\C{ assignment, stop copying }\6
\&{break};\6
\4\&{case} \\{string}:\C{ don't copy them either }\6
\&{do}\5
${}\\{tp}\PP;{}$\5
\&{while} ${}({*}\\{tp}\I\\{string}\W\\{tp}<\\{tk});{}$\6
\&{break};\6
\4\&{case} \.{','}:\5
\&{case} \.{';'}:\6
\&{if} ${}(\R\\{braces}){}$\1\5
${}\\{copy\_on}\K\T{1}{}$;\C{ restart copying, assignment terminated }\2\6
\&{break};\6
\4\&{default}:\6
\&{if} ${}(\|c\G\T{\~200}){}$\5
${}\{{}$\1\6
${}\PP\\{tp};{}$\6
\&{if} (\\{copy\_on})\5
${}\{{}$\1\6
\\{app\_repl}(\|c);\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\|c\E\T{\~320}\W{*}\\{tp}\E\T{0}){}$\5
${}\{{}$\C{ \PB{\T{\~150000}} means \&{\#line} info }\1\6
\&{if} (\\{copy\_on})\5
${}\{{}$\1\6
${}\PP\\{tp};{}$\6
${}\\{app\_repl}({*}\\{tp});{}$\6
${}\PP\\{tp};{}$\6
${}\\{app\_repl}({*}\\{tp});{}$\6
${}\PP\\{tp};{}$\6
${}\\{app\_repl}({*}\\{tp});{}$\6
${}\PP\\{tp};{}$\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{tp}\MRL{+{\K}}\T{4};{}$\2\6
\4${}\}{}$\2\6
\&{continue};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{copy\_on}\W\|c){}$\1\5
\\{app\_repl}(\|c);\2\6
\4${}\}{}$\2\6
\\{app\_repl}(\.{'\\n'});\6
\&{if} (\\{if\_ndef})\5
${}\{{}$\1\6
\\{app\_repl}(\.{'\#'});\6
${}\\{app\_repl}((\\{id\_endif}\GG\T{8})+\T{\~200});{}$\6
${}\\{app\_repl}(\\{id\_endif}\AND\T{\~377});{}$\6
\\{app\_repl}(\.{'\\n'});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\Q149.
\U143.\fi

\M{161}In order to make exported variables always global, they are collected
in the \PB{\\{var\_sec}} section and inserted after the declarations.
Since the statement is now in this section, it is removed from the original
token list.
\Y\B\4\X161:Move variable to \PB{\\{var\_sec}}\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|j;\7
${}\\{sec}\K{\AND}\\{var\_sec};{}$\6
${}\\{new\_text\_ptr}(\\{sec},\39\T{0});{}$\6
\\{remember\_export\_line}(\|i);\6
\&{for} ${}(\\{tp}\K\\{export\_ref}[\|i];{}$ ${}\\{tp}<\\{tk};{}$ ${}\\{tp}%
\PP){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tp}\G\T{\~200}){}$\5
${}\{{}$\1\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\&{if} ${}({*}\\{tp}\PP\E\T{\~320}\W{*}\\{tp}\E\T{0}{}$)\C{ \PB{\T{\~150000}}
means \&{\#line} info }\1\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{4};{}$ ${}\|j\PP,\39\\{tp}\PP){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\2\6
${}\\{app\_repl}({*}\\{tp});{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}({*}\\{tp}\I\\{ignore}){}$\1\5
${}\\{app\_repl}({*}\\{tp});{}$\2\6
\4${}\}{}$\2\6
\\{app\_repl}(\.{'\\n'});\6
\X145:Remove statement\X;\6
\4${}\}{}$\2\par
\U143.\fi

\M{162}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{remember\_export\_line}(\,);\par
\fi

\M{163}The source file name and the line number the of \PB{\\{export\_ref}[%
\|i]} are
stored in \PB{\\{export\_file\_name}[\|i]} and \PB{\\{export\_line}[\|i]},
respectively.
They should be inserted into the token memory in order to get reasonable
error messages from the compiler.

These information starts with two bytes making up the octal number
\PB{\T{\~150000}} followed by two bytes of line number and an identifier token
that gives the name of the file. During output phase, these tokens will
be converted into a \&{\#line} \CEE/ preprocessor command.
\Y\B\&{void} \\{remember\_export\_line}(\|i)\1\1\6
\&{int} \|i;\2\2\6
${}\{{}$\1\6
\&{int} \|a;\6
\&{char} ${}{*}\\{id};{}$\7
\\{store\_two\_bytes}(\T{\~150000});\6
\\{store\_two\_bytes}(\\{export\_line}[\|i]);\6
${}\\{id}\K\\{export\_file\_name}[\|i];{}$\6
${}\|a\K\\{id\_lookup}(\\{id},\39\\{id}+\\{strlen}(\\{id}),\39\T{0})-\\{name%
\_dir};{}$\6
${}\\{app\_repl}((\|a\GG\T{8})+\T{\~200});{}$\6
${}\\{app\_repl}(\|a\AND\T{\~377});{}$\6
\4${}\}{}$\2\par
\fi

\M{164}While the preceding routines all work during the input phase,
the following routine is called at the end of phase two. It outputs
the sections collected before.
\Y\B\4\X164:Output all exports\X${}\E{}$\6
$\\{output\_export\_section}(\\{exp\_sec},\39\\{Exp\_file},\39\.{"export"});{}$%
\6
${}\\{output\_export\_section}(\\{shr\_sec},\39\\{Shr\_file},\39%
\.{"shared"}){}$;\par
\U48.\fi

\M{165}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{output\_export\_section}(\,);\par
\fi

\M{166}This seems to be almost the same as \PB{$\X55:Write all the named output
files\X$}.
But note that we have to take into account that two consecutive
elements of \PB{\\{text\_info}} can point to the same location in \PB{\\{tok%
\_mem}} because
the first one is that of \PB{\\{exp\_sec}} and the second one is that of
\PB{\\{shr\_sec}}.
Therefore, we have to be careful when setting the \PB{\\{cur\_end}} pointer.
\Y\B\&{void} ${}\\{output\_export\_section}(\\{sec},\39\\{file},\39\\{sec%
\_name}){}$\1\1\6
\&{export\_section} ${}{*}\\{sec};{}$\6
\&{FILE} ${}{*}\\{file};{}$\6
\&{char} ${}{*}\\{sec\_name};\2\2{}$\6
${}\{{}$\1\6
\&{int} \|i;\6
\&{name\_pointer} \\{name};\6
\&{FILE} ${}{*}\\{old\_C\_file};{}$\6
\&{static} \&{char} ${}{*}\\{comments}[\,]\K\{\NULL,\39\.{"typedefs\ \&\
aggregat}\)\.{es"},\39\.{"prototypes\ \&\ declar}\)\.{ations"}\};{}$\7
\&{if} ${}(\R\\{file}){}$\1\5
\&{return};\2\6
${}\\{old\_C\_file}\K\\{C\_file};{}$\6
${}\\{C\_file}\K\\{file};{}$\6
${}\\{cur\_line}\K\T{1};{}$\6
${}\\{name}\K\\{id\_lookup}(\\{sec\_name},\39\\{sec\_name}+\\{strlen}(\\{sec%
\_name}),\39\T{0});{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{num\_export\_sections};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{sec}[\|i].\\{first\_text}){}$\5
${}\{{}$\1\6
${}\\{name}\MG\\{equiv}\K{}$(\&{char} ${}{*}){}$ \\{sec}[\|i]${}.\\{first%
\_text};{}$\6
${}\\{stack\_ptr}\K\\{stack}+\T{1};{}$\6
${}\\{cur\_name}\K\\{name};{}$\6
${}\\{cur\_repl}\K{}$(\&{text\_pointer}) \\{cur\_name}${}\MG\\{equiv};{}$\6
${}\\{cur\_byte}\K\\{cur\_repl}\MG\\{tok\_start};{}$\6
\\{set\_cur\_end}(\,);\6
${}\\{cur\_section}\K\T{0};{}$\6
\&{if} (\\{comments}[\|i])\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"/*\%s*/"},\39\\{comments}[\|i]);{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\6
\&{while} ${}(\\{stack\_ptr}>\\{stack}){}$\1\5
\\{get\_output}(\,);\2\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\6
\&{if} ${}(\R\|i){}$\1\5
\X173:Output transitive import \PB{$\#$ \&{include}}s\X\2\6
\4${}\}{}$\2\6
${}\\{C\_file}\K\\{old\_C\_file};{}$\6
\4${}\}{}$\2\par
\fi

\N{1}{167}Dependency file.
The dependency file contains all the other chapters our
current chapter depends on. All dependency files are stored
relative to the environment variable \PB{\.{DEPDIR}} in a subdirectory
with the same name as the book.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} \\{dep\_dir}[\\{max\_file\_name\_length}];\C{ environment variable {%
\tt DEPDIR} }\par
\fi

\M{168}The dependencies of our current chapter are stored in a dependency list
\PB{\\{dep\_head}}
with nodes of type \PB{\\{dependency\_node}}. Every node contains the name of
the
imported chapter/book, whether it should be transitively passed on to users
of our chapter and a type field which can have one of the following values.
\Y\B\4\D$\\{dep\_import\_chapter}$ \5
\T{1}\C{ chapter name of same book }\par
\B\4\D$\\{dep\_from\_program\_import}$ \5
\T{2}\C{ import from which program }\par
\B\4\D$\\{dep\_from\_library\_import}$ \5
\T{3}\C{ import from which library }\par
\B\4\D$\\{dep\_book\_chapter}$ \5
\T{4}\C{ which chapters of a foreign book we import }\par
\B\4\D$\\{dep\_import\_program}$ \5
\T{5}\C{ we import the whole program }\par
\B\4\D$\\{dep\_import\_library}$ \5
\T{6}\C{ we import the whole library }\par
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{struct} \\{dependency\_node} ${}\{{}$\1\6
\&{struct} \\{dependency\_node} ${}{*}\\{next};{}$\6
\&{sixteen\_bits} \\{dep\_type};\6
\&{boolean} \\{exported};\C{ transitive? }\6
\&{eight\_bits} \\{name}[\T{2}];\C{ may grow depending on the real name length
}\2\6
${}\}{}$;\par
\fi

\M{169}The root of the dependency list is stored in \PB{\\{dep\_head}}.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{struct} \\{dependency\_node} ${}{*}\\{dep\_head}{}$;\par
\fi

\M{170}
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{dep\_head}\K\NULL{}$;\par
\fi

\M{171}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{static} \&{void} \\{directly\_depending\_on}(\,);\par
\fi

\M{172}All chapters and books we are directly depending on, are stored in the
dependency list.
Each entry in the list is unique.
Memory for dependency nodes is allocated dynamically.
\Y\B\&{static} \&{void} ${}\\{directly\_depending\_on}(\\{name},\39\\{type},\39%
\\{exported}){}$\1\1\6
\&{char} ${}{*}\\{name};{}$\6
\&{sixteen\_bits} \\{type};\6
\&{boolean} \\{exported};\2\2\6
${}\{{}$\1\6
\&{struct} \\{dependency\_node} ${}{*}\\{d\_node},{}$ ${}{*}\\{tail};{}$\7
\&{if} (\\{dep\_head})\1\6
\&{for} ${}(\\{tail}\K\\{dep\_head};{}$ ${}\\{tail}\MG\\{next};{}$ ${}\\{tail}%
\K\\{tail}\MG\\{next}){}$\1\6
\&{if} ${}(\\{type}\E\\{tail}\MG\\{dep\_type}\W\\{strcmp}(\\{name},\39\\{tail}%
\MG\\{name})\E\T{0}){}$\5
${}\{{}$\1\6
${}\\{tail}\MG\\{exported}\MRL{{\OR}{\K}}\\{exported};{}$\6
\&{return};\6
\4${}\}{}$\2\2\2\6
${}\\{d\_node}\K{}$(\&{struct} \\{dependency\_node} ${}{*}){}$ \\{malloc}(%
\&{sizeof}(\&{struct} \\{dependency\_node})${}+\\{strlen}(\\{name})-\T{1});{}$\6
\&{if} ${}(\R\\{d\_node}){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory\ for\ dep}\)\.{endency\ node:"},\39\\{name});{}$%
\2\6
${}\\{strcpy}(\\{d\_node}\MG\\{name},\39\\{name});{}$\6
${}\\{d\_node}\MG\\{dep\_type}\K\\{type};{}$\6
${}\\{d\_node}\MG\\{exported}\K\\{exported};{}$\6
${}\\{d\_node}\MG\\{next}\K\NULL;{}$\6
\&{if} ${}(\\{dep\_head}\E\NULL){}$\1\5
${}\\{dep\_head}\K\\{d\_node};{}$\2\6
\&{else}\1\5
${}\\{tail}\MG\\{next}\K\\{d\_node};{}$\2\6
\4${}\}{}$\2\par
\fi

\M{173}If we depend on certain other chapters or books, and we want to pass
these dependencies on to users of our chapter (transitive imports),
we insert \PB{$\#$ \&{include}}s for what we use in our export/shared file.

References to other chapters in our book are only inserted in shared files,
since we do not want to pass shared information on to other books.
\Y\B\4\X173:Output transitive import \PB{$\#$ \&{include}}s\X${}\E{}$\6
${}\{{}$\1\6
\&{struct} \\{dependency\_node} ${}{*}\\{d\_node};{}$\6
\&{char} ${}{*}\\{ext};{}$\7
\&{if} (\\{dep\_head})\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\%s"},\39\.{"/*\ transitive\ impor}\)\.{t\ includes\
*/"});{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\6
\&{for} ${}(\\{d\_node}\K\\{dep\_head};{}$ \\{d\_node}; ${}\\{d\_node}\K\\{d%
\_node}\MG\\{next}){}$\1\6
\&{if} ${}(\\{d\_node}\MG\\{exported}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{d\_node}\MG\\{dep\_type}\E\\{dep\_from\_program\_import}\V\\{d%
\_node}\MG\\{dep\_type}\E\\{dep\_from\_library\_import}){}$\1\5
\&{continue};\2\6
\&{if} ${}(\\{d\_node}\MG\\{dep\_type}\E\\{dep\_import\_chapter}){}$\5
${}\{{}$\1\6
${}\\{ext}\K\.{"shr"};{}$\6
\&{if} ${}(\\{file}\E\\{Exp\_file}{}$)\C{ don't include shared files in export
files }\1\6
\&{continue};\2\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{ext}\K\.{"exp"};{}$\2\6
${}\\{C\_printf}(\.{"\#include\ \\"\%s"},\39\\{d\_node}\MG\\{name});{}$\6
${}\\{C\_printf}(\.{".\%s\\""},\39\\{ext});{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\2\6
\4${}\}{}$\2\par
\U166.\fi

\M{174}Write includes for files we are directly depending on.
\Y\B\4\X174:Output direct import \PB{$\#$ \&{include}}s\X${}\E{}$\6
${}\{{}$\1\6
\&{struct} \\{dependency\_node} ${}{*}\\{d\_node};{}$\7
\&{if} (\\{dep\_head})\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\%s"},\39\.{"/*\ direct\ import\ in}\)\.{cludes\ */"});{}$%
\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\6
\&{for} ${}(\\{d\_node}\K\\{dep\_head};{}$ \\{d\_node}; ${}\\{d\_node}\K\\{d%
\_node}\MG\\{next}){}$\1\6
\&{if} ${}(\\{d\_node}\MG\\{dep\_type}\I\\{dep\_from\_program\_import}\W\\{d%
\_node}\MG\\{dep\_type}\I\\{dep\_from\_library\_import}){}$\1\6
\&{if} ${}(\\{d\_node}\MG\\{exported}\E\T{0}\V(\\{used\_exports}\AND\\{exp%
\_shared})\E\T{0}){}$\5
${}\{{}$\1\6
${}\\{C\_printf}(\.{"\#include\ \\"\%s"},\39\\{d\_node}\MG\\{name});{}$\6
${}\\{C\_printf}(\.{".\%s\\""},\39\\{d\_node}\MG\\{dep\_type}\E\\{dep\_import%
\_chapter}\?\.{"shr"}:\.{"exp"});{}$\6
\\{flush\_buffer}(\,);\6
\4${}\}{}$\2\2\2\6
\4${}\}{}$\2\par
\U60.\fi

\M{175}In order to keep track of dependencies, \.{mCTANGLE} creates so called
dependency files in the directory
\.{\$(DEPDIR)/$\langle\hbox{\it bookname}\rangle$}, one for the book
and each chapter.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{FILE} ${}{*}\\{book\_dep\_file};{}$\6
\&{char} \\{dep\_file\_name}[\\{max\_file\_name\_length}];\par
\fi

\M{176}The dependency file for the book only states the chapters the book
consists of.
\Y\B\4\X176:Open dependency file for book\X${}\E{}$\6
${}\{{}$\1\6
${}\\{exp\_file\_name\_of}(\\{dep\_file\_name},\39\\{file\_name}[\T{0}],\39%
\.{".dep"});{}$\6
${}\\{book\_dep\_file}\K\\{fopen}(\\{dep\_file\_name},\39\.{"w"});{}$\6
\&{if} ${}(\R\\{book\_dep\_file}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ create\ dep}\)\.{endency\ file\ for\ boo}\)\.{k:"},%
\39\\{dep\_file\_name});{}$\2\6
\4${}\}{}$\2\par
\U206.\fi

\M{177}The dependency file for a chapter contains a list of all files
the chapter directly depends on. Each entry is on a line of its own.
It starts either with a space or an asterisk '\.{*}', the latter
is indicating that this dependency is exported to other books using
this chapter. Following this, the dependency type as a number is written.
This can be \PB{\\{dep\_book\_chapter}}, \PB{\\{dep\_from\_library\_import}}
and so on.

The rest of the line contains the name of the book or chapter we
depend on.
\Y\B\4\X177:Write dependency file for chapter\X${}\E{}$\6
${}\{{}$\1\6
\&{FILE} ${}{*}\\{chapter\_dep\_file};{}$\6
\&{struct} \\{dependency\_node} ${}{*}\\{d\_node};{}$\7
${}\\{exp\_file\_name\_of}(\\{dep\_file\_name},\39\\{chapter\_name},\39%
\.{".dep"});{}$\6
${}\\{chapter\_dep\_file}\K\\{fopen}(\\{dep\_file\_name},\39\.{"w"});{}$\6
\&{if} ${}(\R\\{chapter\_dep\_file}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ create\ dep}\)\.{endency\ file\ for\ cha}\)%
\.{pter:"},\39\\{dep\_file\_name}){}$;\2\7
\&{for} ${}(\\{d\_node}\K\\{dep\_head};{}$ \\{d\_node}; ${}\\{d\_node}\K\\{d%
\_node}\MG\\{next}){}$\1\5
${}\\{fprintf}(\\{chapter\_dep\_file},\39\.{"\%c\%d\ \%s\\n"},\39\\{d\_node}\MG%
\\{exported}\?\.{'*'}:\.{'\ '},\39\\{d\_node}\MG\\{dep\_type},\39\\{d\_node}\MG%
\\{name}){}$;\2\7
\\{fclose}(\\{chapter\_dep\_file});\6
${}\\{chapter\_dep\_head}[\\{chapter\_no}]\K\\{dep\_head}{}$;\C{ dependency
list for our chapter }\6
\4${}\}{}$\2\par
\U223.\fi

\M{178}In case a retranslation of the current chapter is not necessary,
we read the old dependency file in order to know which files we are
directly depending on.
\Y\B\4\X178:Read dependency file of chapter\X${}\E{}$\6
${}\{{}$\1\6
\&{FILE} ${}{*}\\{chapter\_dep\_file};{}$\6
\&{int} \\{type};\6
\&{char} ${}{*}\\{cp},{}$ \\{exp};\7
${}\\{dep\_head}\K\NULL{}$;\C{ reset dependency list }\6
${}\\{exp\_file\_name\_of}(\\{dep\_file\_name},\39\\{chapter\_name},\39%
\.{".dep"});{}$\6
${}\\{chapter\_dep\_file}\K\\{fopen}(\\{dep\_file\_name},\39\.{"r"});{}$\6
\&{if} ${}(\R\\{chapter\_dep\_file}){}$\1\5
\\{err\_print}(\.{"!\ No\ dependency\ fil}\)\.{e\\n"});\2\6
\&{else}\5
${}\{{}$\1\6
\&{while} ${}(\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39%
\\{chapter\_dep\_file})){}$\5
${}\{{}$\1\6
${}\\{cp}\K\\{strchr}(\\{buffer},\39\.{'\\n'});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{sscanf}(\\{buffer},\39\.{"\%c\%d"},\39{\AND}\\{exp},\39{\AND}%
\\{type});{}$\6
${}\\{cp}\K\\{strchr}(\\{buffer}+\T{1},\39\.{'\ '});{}$\6
\&{if} ${}(\R\\{cp}){}$\1\5
\&{continue};\2\6
${}\\{cp}\PP;{}$\6
${}\\{directly\_depending\_on}(\\{cp},\39\\{type},\39\\{exp}\I\.{'\ '});{}$\6
\4${}\}{}$\2\6
\\{fclose}(\\{chapter\_dep\_file});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U223.\fi

\N{2}{179}Full dependencies of all chapters.
Up to now, we only have the direct dependencies of all chapters,
i.e.~the dependencies we know as a result of import commands.
We now want to use the dependency files to find all parts
each chapter depends on. This is done after we have translated all
chapters.

The dependency list \PB{\\{dep\_head}} for chapter $i$
with all direct dependencies lies in \PB{\\{chapter\_dep\_head}[\|i]}.

\fi

\M{180}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{create\_dependencies}(\,);\6
\&{void} \\{add\_transitive\_deps}(\,);\6
\&{void} \\{add\_chapter\_to\_dep}(\,);\6
\&{void} \\{add\_book\_to\_dep}(\,);\par
\fi

\M{181}For our \.{makefile}
we also have to know indirect dependencies. All those together form
the make dependencies. They are collected in a separate list for each chapter.
\Y\B\4\X18:Typedef declarations\X${}\mathrel+\E{}$\6
\&{struct} \\{make\_dep} ${}\{{}$\1\6
\&{struct} \\{make\_dep} ${}{*}\\{next};{}$\6
\&{char} \\{name}[\T{2}];\2\6
${}\}{}$;\par
\fi

\M{182}Dependencies for each chapter.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{struct} \\{make\_dep} ${}{*}\\{ch\_make\_dep}[\\{max\_chapters}]{}$;\par
\fi

\M{183}Let chapter \PB{\\{ch}} depend on \PB{\\{name}}.
\Y\B\&{struct} \\{make\_dep} ${}{*}\\{add\_make\_dep}(\\{ch},\39\\{name}){}$\1%
\1\6
\&{char} ${}{*}\\{name};\2\2{}$\6
${}\{{}$\1\6
\&{struct} \\{make\_dep} ${}{*}\\{md},{}$ ${}{*}\\{last\_md};{}$\7
\&{for} ${}(\\{md}\K\\{ch\_make\_dep}[\\{ch}];{}$ \\{md}; ${}\\{md}\K\\{md}\MG%
\\{next}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{strcmp}(\\{md}\MG\\{name},\39\\{name})){}$\1\5
\&{return} ${}\NULL;{}$\2\6
${}\\{last\_md}\K\\{md};{}$\6
\4${}\}{}$\2\6
${}\\{md}\K{}$(\&{struct} \\{make\_dep} ${}{*}){}$ \\{malloc}(\&{sizeof}(%
\&{struct} \\{make\_dep})${}+\\{strlen}(\\{name})-\T{1});{}$\6
\&{if} ${}(\R\\{md}){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory"},\39\.{"\ for\ make\ dependenc}\)\.{y\
name"});{}$\2\6
${}\\{md}\MG\\{next}\K\NULL;{}$\6
${}\\{strcpy}(\\{md}\MG\\{name},\39\\{name});{}$\6
\&{if} (\\{ch\_make\_dep}[\\{ch}])\1\5
${}\\{last\_md}\MG\\{next}\K\\{md};{}$\2\6
\&{else}\1\5
${}\\{ch\_make\_dep}[\\{ch}]\K\\{md};{}$\2\6
\&{return} \\{md};\6
\4${}\}{}$\2\par
\fi

\M{184}Since \CEE/ programs are also linked together, we need to keep track of
all books our current book is depending on. Books can either be other
programs related to our book or libraries. If it's a program or a library
is stored in the \PB{\\{type}} member of the following structure.
\Y\B\4\X18:Typedef declarations\X${}\mathrel+\E{}$\6
\&{struct} \\{book\_node} ${}\{{}$\1\6
\&{struct} \\{book\_node} ${}{*}\\{next};{}$\6
\&{int} \\{type};\6
\&{char} \\{name}[\T{2}];\2\6
${}\}{}$;\par
\fi

\M{185}We keep a linked list of all books we are related to.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{struct} \\{book\_node} ${}{*}\\{books\_head}{}$;\par
\fi

\M{186}Let us depend on book \PB{\\{name}} which is of type \PB{\\{type}}.
\Y\B\&{struct} \\{book\_node} ${}{*}\\{add\_book\_dep}(\\{type},\39\\{name}){}$%
\1\1\6
\&{char} ${}{*}\\{name};\2\2{}$\6
${}\{{}$\1\6
\&{struct} \\{book\_node} ${}{*}\\{bn},{}$ ${}{*}\\{last\_bn}\K\NULL,{}$ ${}{*}%
\\{found}\K\NULL,{}$ ${}{*}\\{last\_found};{}$\7
\&{for} ${}(\\{bn}\K\\{books\_head};{}$ \\{bn}; ${}\\{bn}\K\\{bn}\MG%
\\{next}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{strcmp}(\\{bn}\MG\\{name},\39\\{name})){}$\5
${}\{{}$\C{ book already in list }\1\6
${}\\{found}\K\\{bn};{}$\6
${}\\{last\_found}\K\\{last\_bn};{}$\6
\4${}\}{}$\2\6
${}\\{last\_bn}\K\\{bn};{}$\6
\4${}\}{}$\2\6
\&{if} (\\{found})\5
${}\{{}$\C{ the book is not new, but already part of the list }\6
\8\#\&{ifdef} \.{MOVE\_TO\_TAIL}\1\6
\&{if} ${}(\\{found}\I\\{last\_bn}){}$\5
${}\{{}$\C{ if not already there, move \PB{\\{found}} to tail of list }\1\6
\&{if} (\\{last\_found})\1\5
${}\\{last\_found}\MG\\{next}\K\\{found}\MG\\{next};{}$\2\6
\&{else}\1\5
${}\\{books\_head}\K\\{found}\MG\\{next};{}$\2\6
${}\\{last\_bn}\MG\\{next}\K\\{found};{}$\6
${}\\{found}\MG\\{next}\K\NULL;{}$\6
\4${}\}{}$\2\6
\8\#\&{endif}\6
\&{return} ${}\NULL;{}$\6
\4${}\}{}$\2\6
${}\\{bn}\K{}$(\&{struct} \\{book\_node} ${}{*}){}$ \\{malloc}(\&{sizeof}(%
\&{struct} \\{book\_node})${}+\\{strlen}(\\{name})-\T{1});{}$\6
\&{if} ${}(\R\\{bn}){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory"},\39\.{"\ for\ book\ dependenc}\)\.{y\
name"});{}$\2\6
${}\\{bn}\MG\\{next}\K\NULL;{}$\6
${}\\{bn}\MG\\{type}\K\\{type};{}$\6
${}\\{strcpy}(\\{bn}\MG\\{name},\39\\{name});{}$\6
\&{if} (\\{books\_head})\1\5
${}\\{last\_bn}\MG\\{next}\K\\{bn};{}$\2\6
\&{else}\1\5
${}\\{books\_head}\K\\{bn};{}$\2\6
\&{return} \\{bn};\6
\4${}\}{}$\2\par
\fi

\M{187}For each chapter $0\le ch<chapter\_no$ we have to collect all
dependencies,
so that we know which files our chapters depends on. This information is
useful in order to create \.{makefile}-dependency constants.
\Y\B\&{void} \\{create\_dependencies}(\\{ch})\1\1\2\2\6
${}\{{}$\1\6
\&{struct} \\{dependency\_node} ${}{*}\\{dep};{}$\6
\&{char} ${}{*}\\{cp};{}$\7
${}\\{ch\_make\_dep}[\\{ch}]\K\NULL;{}$\6
\&{for} ${}(\\{dep}\K\\{chapter\_dep\_head}[\\{ch}];{}$ \\{dep}; ${}\\{dep}\K%
\\{dep}\MG\\{next}){}$\1\6
\&{if} ${}(\\{dep}\MG\\{dep\_type}\E\\{dep\_import\_chapter}){}$\5
${}\{{}$\1\6
${}\\{strcpy}(\\{dep\_file\_name},\39\\{dep}\MG\\{name});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{dep\_file\_name});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{strcat}(\\{dep\_file\_name},\39\.{".shr"});{}$\6
${}\\{add\_make\_dep}(\\{ch},\39\\{dep\_file\_name});{}$\6
${}\\{exp\_file\_name\_of}(\\{dep\_file\_name},\39\\{dep}\MG\\{name},\39%
\.{".dep"});{}$\6
${}\\{add\_chapter\_to\_dep}(\\{ch},\39\\{dep\_import\_chapter});{}$\6
\4${}\}{}$\2\2\6
\&{for} ${}(\\{dep}\K\\{chapter\_dep\_head}[\\{ch}];{}$ \\{dep}; ${}\\{dep}\K%
\\{dep}\MG\\{next}){}$\1\5
${}\\{add\_transitive\_deps}(\\{ch},\39\\{dep}\MG\\{dep\_type},\39\\{dep}\MG%
\\{name});{}$\2\6
\4${}\}{}$\2\par
\fi

\M{188}Each dependency node can have dependencies on its own. We call such
dependencies {\it transitive}. The following function recursivly
adds all transitive dependencies of the given dependency (\PB{\\{type}} and
\PB{\\{name}} stated) to the dependency list of chapter \PB{\\{ch}}.
\Y\B\&{void} ${}\\{add\_transitive\_deps}(\\{ch},\39\\{type},\39\\{name}){}$\1%
\1\6
\&{char} ${}{*}\\{name};\2\2{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp};{}$\7
${}\\{strcpy}(\\{dep\_file\_name},\39\\{dep\_dir});{}$\6
${}\\{strcat}(\\{dep\_file\_name},\39\\{name});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{dep\_file\_name});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{strcat}(\\{dep\_file\_name},\39\.{".dep"});{}$\6
\&{switch} (\\{type})\5
${}\{{}$\1\6
\4\&{case} \\{dep\_from\_program\_import}:\5
\&{case} \\{dep\_from\_library\_import}:\5
${}\\{add\_book\_dep}(\\{type}\E\\{dep\_from\_program\_import}\?\\{book%
\_program}:\\{book\_library},\39\\{name});{}$\6
\&{break};\6
\4\&{case} \\{dep\_book\_chapter}:\5
${}\\{add\_chapter\_to\_dep}(\\{ch},\39\\{type});{}$\6
\&{break};\6
\4\&{case} \\{dep\_import\_program}:\5
\&{case} \\{dep\_import\_library}:\5
${}\\{add\_book\_dep}(\\{type}\E\\{dep\_import\_program}\?\\{book\_program}:%
\\{book\_library},\39\\{name});{}$\6
\\{add\_book\_to\_dep}(\\{ch});\6
\&{break};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{189}After a \PB{\\{dep\_from\_program\_import}} or a \PB{\\{dep\_from%
\_library\_import}} there
are a couple of \PB{\\{dep\_book\_chapter}} nodes that indicate the chapters of
the given book we are depending on. Each chapter's dependencies are
added to our dependency list.

The file name of the dependency file can already be found in \PB{\\{dep\_file%
\_name}}.
\Y\B\&{void} ${}\\{add\_chapter\_to\_dep}(\\{ch},\39\\{type}){}$\1\1\2\2\6
${}\{{}$\1\6
\&{FILE} ${}{*}\|f;{}$\6
\&{char} ${}{*}\\{cp},{}$ \\{exp}${},{}$ ${}{*}\\{buf},{}$ ${}{*}%
\\{depname};{}$\7
\&{if} ${}(\\{type}\E\\{dep\_book\_chapter}){}$\5
${}\{{}$\C{ add export file to make dependency list }\1\6
${}\\{cp}\K\\{dep\_file\_name}+\\{strlen}(\\{dep\_file\_name})-\T{3};{}$\6
${}\\{strcpy}(\\{cp},\39\.{"exp"});{}$\6
\&{if} ${}(\R\\{add\_make\_dep}(\\{ch},\39\\{dep\_file\_name}){}$)\C{ add it }%
\1\6
\&{return};\C{ was already there }\2\6
${}\\{strcpy}(\\{cp},\39\.{"dep"});{}$\6
\4${}\}{}$\2\6
${}\|f\K\\{fopen}(\\{dep\_file\_name},\39\.{"r"});{}$\6
\&{if} ${}(\R\|f){}$\5
${}\{{}$\1\6
${}\\{printf}(\.{"\\n!\ Cannot\ open\ cha}\)\.{pter\ dependency\ file}\)\.{\ %
\%s\\n"},\39\\{dep\_file\_name});{}$\6
\\{mark\_error};\6
\&{return};\6
\4${}\}{}$\2\6
\&{while} ${}(\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39\|f)){}$%
\5
${}\{{}$\1\6
${}\\{cp}\K\\{strrchr}(\\{buffer},\39\.{'\\n'});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0}{}$;\C{ remove newline }\2\6
${}\\{sscanf}(\\{buffer},\39\.{"\%c\%d"},\39{\AND}\\{exp},\39{\AND}%
\\{type});{}$\6
\&{if} ${}(\\{exp}\E\.{'\ '}){}$\1\5
\&{continue};\C{ no transitive dependency }\2\6
${}\\{cp}\K\\{buffer}+\T{1};{}$\6
\&{while} ${}(\\{isdigit}({*}\\{cp})){}$\1\5
${}\\{cp}\PP;{}$\2\6
\&{while} ${}(\\{isspace}({*}\\{cp})){}$\1\5
${}\\{cp}\PP;{}$\2\6
${}\\{buf}\K\\{strmem}(\\{cp});{}$\6
${}\\{depname}\K\\{strmem}(\\{dep\_file\_name});{}$\6
${}\\{add\_transitive\_deps}(\\{ch},\39\\{type},\39\\{buf});{}$\6
${}\\{strcpy}(\\{dep\_file\_name},\39\\{depname});{}$\6
\\{free}(\\{depname});\6
\\{free}(\\{buf});\6
\4${}\}{}$\2\6
\\{fclose}(\|f);\6
\4${}\}{}$\2\par
\fi

\M{190}This adds the whole book to the dependency list of chapter \PB{\\{ch}}.
The book's dependency file only gives the various chapters.
\Y\B\&{void} \\{add\_book\_to\_dep}(\\{ch})\1\1\2\2\6
${}\{{}$\1\6
\&{FILE} ${}{*}\|f;{}$\6
\&{char} ${}{*}\\{cp};{}$\7
${}\|f\K\\{fopen}(\\{dep\_file\_name},\39\.{"r"});{}$\6
\&{if} ${}(\R\|f){}$\5
${}\{{}$\1\6
${}\\{printf}(\.{"\\n!\ Cannot\ open\ boo}\)\.{k\ dependency\ file\ \%s}\)\.{%
\\n"},\39\\{dep\_file\_name});{}$\6
\\{mark\_error};\6
\&{return};\6
\4${}\}{}$\2\6
\&{while} ${}(\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39\|f)){}$%
\5
${}\{{}$\1\6
${}\\{cp}\K\\{strrchr}(\\{buffer},\39\.{'\\n'});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{cp}\K\\{file\_name\_part}(\\{dep\_file\_name});{}$\6
${}\\{strcpy}(\\{cp},\39\\{buffer});{}$\6
${}\\{strcat}(\\{cp},\39\.{".dep"});{}$\6
${}\\{add\_chapter\_to\_dep}(\\{ch},\39\\{dep\_book\_chapter});{}$\6
\4${}\}{}$\2\6
\\{fclose}(\|f);\6
\4${}\}{}$\2\par
\fi

\N{1}{191}Import commands.
Of course, if we can export something we also have to have the
possibility of importing data. In the following sections we will
deal with import. There are three different sources where we can
import from. First of all we can import data from another chapter
of the same book, or we can import data from another book, which
can either be a library or another program.

Chapters from the same book are imported using \&{import chapter} $\langle$%
\.{chapter}%
$\rangle$ $\{,\langle$\.{chapter}$\rangle\}$.
If we want to import someting from a library,
we either write \&{import} \&{library} $\langle$\.{book}$\rangle$ $\{,\langle$%
\.{book}$\rangle\}$ in order
to import all chapters of that book, or we write
\&{from} \&{library} $\langle$\.{book}$\rangle$ \&{import}
$\langle$\.{chapter}$\rangle$ $\{,\langle$\.{chapter}$\rangle\}$
if we only want to import some chapters of a library. If we want to
import from another program rather than from a library we simply exchange
the keyword \&{library} by \&{program}.

Like export commands, import commands are handled during phase one, since
we need them before we start with phase two. When we encounter an import
command, we store a reference to the corresponding token in the array
\PB{\\{import\_ref}}. After we have read a full section, we make a closer look
on these commands. This ensures, that all commands have been properly
tokenized when we are parsing them.

Import commands can also be transitive, which means, that
this import command should be automatically
exported to another \.{CWEB} file, that imports the current one.
Transitive import commands are written into the dependency file, so other
programs will automatically depend on them.
\Y\B\4\D$\\{max\_imports}$ \5
\T{64}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{eight\_bits} ${}{*}\\{import\_ref}[\\{max\_imports}];{}$\6
\&{sixteen\_bits} \\{import\_idx};\C{ last unused \PB{\\{import\_ref}} }\par
\fi

\M{192}
\Y\B\4\X20:Set initial values\X${}\mathrel+\E{}$\6
$\\{import\_idx}\K\T{0}{}$;\par
\fi

\M{193}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{remember\_import}(\,);\par
\fi

\M{194}This is called whenever \PB{\\{scan\_repl}} sees an import command like %
\&{import}.
\Y\B\&{void} \\{remember\_import}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{import\_idx}\G\\{max\_imports}){}$\1\5
\\{overflow}(\.{"imports\ per\ section}\)\.{"});\2\6
${}\\{import\_ref}[\\{import\_idx}]\K\\{tok\_ptr};{}$\6
${}\\{import\_idx}\PP;{}$\6
\4${}\}{}$\2\par
\fi

\M{195}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{process\_imports}(\,);\par
\fi

\M{196}Now we have read in a section and it contains \PB{\\{import\_idx}}
import
commands. Now we will handle them.
\Y\B\&{void} \\{process\_imports}(\,)\1\1 $\{$ \&{int} \|i${},{}$ \|j;\6
\&{eight\_bits} ${}{*}\\{tk};{}$\6
\&{sixteen\_bits} \|a;\6
\&{boolean} \\{exported};\C{ should current import command be exported? }\6
\&{char} \\{name}[\\{max\_quoted\_name}]; \&{for} ${}(\|i\K\|j\K\T{0};{}$ ${}%
\|i<\\{import\_idx};{}$ ${}\|i\PP)$ $\{$ $\\{tk}\K\\{import\_ref}[\|i];{}$\6
${}\\{exported}\K\T{0}{}$;\C{ default: not transitive }\6
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250})$ $\{{}$\C{ import keyword
is an identifier }\6
$\|a\K(\\{tk}[\T{0}]-\T{\~200})\LL\T{8}\OR\\{tk}[\T{1}];{}$\6
${}\\{tk}\MRL{+{\K}}\T{2}{}$;\C{ skip the keyword }\6
\&{if} ${}(\|a\E\\{id\_from})$ \X199:we encountered {\bf from} at \PB{\\{tk}}\X
\6
\&{else}\1\6
\&{if} ${}(\|a\E\\{id\_import}){}$\1\5
\X201:we encountered {\bf import} at \PB{\\{tk}}\X\2\2\6
$\}$ \6
\&{if} (\\{exported})\1\5
${}\\{used\_exports}\MRL{{\OR}{\K}}\\{exp\_export};{}$\2\6
$\}$ $\\{import\_idx}\K\T{0};$ $\}{}$\par
\fi

\M{197}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{static} \&{eight\_bits} ${}{*}\\{get\_quoted\_name}(\,){}$;\par
\fi

\M{198}If \PB{\\{tk}} points to the beginning of a \PB{\\{string}}, we get the
string into
\PB{\\{buffer}} up to a maximum number of \PB{$\\{max\_quoted\_name}-\T{1}$}
characters.
\Y\B\4\D$\\{max\_quoted\_name}$ \5
\T{60}\par
\Y\B\&{static} \&{eight\_bits} ${}{*}\\{get\_quoted\_name}(\\{tk},\39%
\\{buffer}){}$\1\1\6
\&{eight\_bits} ${}{*}\\{tk},{}$ ${}{*}\\{buffer};\2\2{}$\6
${}\{{}$\1\6
\&{int} \|i${}\K\T{0};{}$\7
\&{if} ${}({*}\\{tk}\E\\{string}){}$\1\5
${}\\{tk}\MRL{+{\K}}\T{2};{}$\2\6
\&{do}\5
${}\{{}$\1\6
\&{if} ${}(\|i\G\\{max\_quoted\_name}-\T{1}){}$\5
${}\{{}$\1\6
${}\\{buffer}[\\{max\_quoted\_name}-\T{1}]\K\T{0};{}$\6
${}\\{fatal}(\.{"!\ Name\ too\ long:"},\39\\{buffer});{}$\6
\4${}\}{}$\2\6
${}\\{buffer}[\|i\PP]\K{*}\\{tk};{}$\6
\4${}\}{}$\2\5
\&{while} ${}({*}\PP\\{tk}\I\\{string});{}$\6
${}\\{buffer}[\|i-\T{1}]\K\T{0};{}$\6
\&{return} ${}\PP\\{tk};{}$\6
\4${}\}{}$\2\par
\fi

\M{199}If we have encountered an import statement like
$$\hbox{\#\&{from library} \.{"libdir/mylib"} \&{import} [\&{transitively}]
\PB{\.{"chapter\_one"}}, \PB{\.{"chapter\_three"}}}$$
\noindent
then we must insert a dependency node for the book (type \PB{\\{dep\_from%
\_import}})
and for every stated chapter (type \PB{\\{dep\_book\_chapter}}).

All chapter names are relative to the book directory.
\Y\B\4\X199:we encountered {\bf from} at \PB{\\{tk}}\X${}\E{}$\6
${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{cp}\K\\{tk}-\T{2};{}$\6
\&{char} ${}{*}\\{ch\_name};{}$\6
\&{int} \\{dep\_type};\7
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}){}$\5
${}\{{}$\C{ import keyword followed by another identifier }\1\6
${}\|a\K(\\{tk}[\T{0}]-\T{\~200})\LL\T{8}\OR\\{tk}[\T{1}];{}$\6
${}\\{tk}\MRL{+{\K}}\T{2};{}$\6
\&{if} ${}(\|a\E\\{id\_program}\V\|a\E\\{id\_library}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tk}\E\\{string}){}$\5
${}\{{}$\C{ a string should follow }\1\6
${}\\{tk}\K\\{get\_quoted\_name}(\\{tk},\39\\{name});{}$\6
\X200:\PB{\\{name}}$\leftarrow$\PB{\\{name}}\.{/}\PB{\\{name}}\X;\6
${}\\{dep\_type}\K\|a\E\\{id\_program}\?\\{dep\_from\_program\_import}:\\{dep%
\_from\_library\_import};{}$\6
${}\\{ch\_name}\K\\{file\_name\_part}(\\{name}){}$;\C{ all chapters are
relative to book directory }\6
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}){}$\5
${}\{{}$\1\6
${}\|a\K(\\{tk}[\T{0}]-\T{\~200})\LL\T{8}\OR\\{tk}[\T{1}];{}$\6
${}\\{tk}\MRL{+{\K}}\T{2};{}$\6
\&{if} ${}(\|a\E\\{id\_import}){}$\5
${}\{{}$\C{ might be follow by transitively }\1\6
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}\W(\\{tk}[\T{0}]-\T{\~200})%
\LL\T{8}\OR\\{tk}[\T{1}]\E\\{id\_transitively}){}$\5
${}\{{}$\1\6
${}\\{exported}\K\T{1};{}$\6
${}\\{tk}\MRL{+{\K}}\T{2};{}$\6
\4${}\}{}$\2\6
${}\\{directly\_depending\_on}(\\{name},\39\\{dep\_type},\39\\{exported});{}$\6
\&{while} ${}({*}\\{tk}\E\\{string}){}$\5
${}\{{}$\1\6
${}\\{tk}\K\\{get\_quoted\_name}(\\{tk},\39\\{ch\_name});{}$\6
${}\\{directly\_depending\_on}(\\{name},\39\\{dep\_book\_chapter},\39%
\\{exported});{}$\6
\&{if} ${}({*}\\{tk}\E\.{','}){}$\1\5
${}\\{tk}\PP;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ 'import'\ expected}\)\.{\ after\ book\ name"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ 'import'\ expected}\)\.{\ after\ book\ name"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ from\ where}\)\.{?"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ source\ mus}\)\.{t\ be\ program\ or\ libr}\)%
\.{ary"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ from\ where}\)\.{\ (program\ or\ library}\)%
\.{)?"});\2\6
\&{do}\5
${}{*}\\{cp}\PP\K\\{ignore};{}$\5
\&{while} ${}(\\{cp}<\\{tk}){}$;\C{ remove import command from token list }\6
\4${}\}{}$\2\par
\U196.\fi

\M{200}In \PB{\\{name}} we can find the name of the book we import from.
Since the name of the export file is
\.{\$(DEPDIR)/{\it bookname}/{\it bookname}.exp}, we double \PB{\\{name}},
which means that for a string \PB{\.{"mybook"}} we create a string
\PB{\.{"mybook/mybook"}}.
\Y\B\4\X200:\PB{\\{name}}$\leftarrow$\PB{\\{name}}\.{/}\PB{\\{name}}\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\R\\{strchr}(\\{name},\39\\{file\_name\_separator})){}$\5
${}\{{}$\1\6
\&{int} \\{len}${}\K\\{strlen}(\\{name});{}$\7
${}\\{strcpy}(\\{name}+\\{len}+\T{1},\39\\{name});{}$\6
${}\\{name}[\\{len}]\K\\{file\_name\_separator};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\Us199\ET201.\fi

\M{201}If we see a statement like
$$\hbox{\#\&{import chapter} \PB{\.{"chapter\_two"}}}$$
\noindent
we must insert a dependency node of type \PB{\\{dep\_import\_chapter}} for each
chapter.
In case of a program or library like
$$\hbox{\#\&{import program} \PB{\.{"book\_two/book\_two"}}, \PB{\.{"book%
\_three/book\_thr}\)\.{ee"}}}$$
\noindent we must create a dependency node of type \PB{\\{dep\_import%
\_program}} for
each book.
\&{import} might be followed by \&{transitively}.
\Y\B\4\X201:we encountered {\bf import} at \PB{\\{tk}}\X${}\E{}$\6
${}\{{}$\1\6
\&{eight\_bits} ${}{*}\\{cp}\K\\{tk}-\T{2};{}$\6
\&{int} \\{type};\7
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}\W(\\{tk}[\T{0}]-\T{\~200})%
\LL\T{8}\OR\\{tk}[\T{1}]\E\\{id\_transitively}){}$\5
${}\{{}$\1\6
${}\\{tk}\MRL{+{\K}}\T{2};{}$\6
${}\\{exported}\K\T{1}{}$;\C{ import transitively }\6
\4${}\}{}$\2\6
\&{if} ${}(\T{\~200}\Z{*}\\{tk}\W{*}\\{tk}<\T{\~250}){}$\5
${}\{{}$\C{ import keyword followed by another identifier }\1\6
${}\|a\K(\\{tk}[\T{0}]-\T{\~200})\LL\T{8}\OR\\{tk}[\T{1}];{}$\6
${}\\{tk}\MRL{+{\K}}\T{2};{}$\6
\&{if} ${}(\|a\E\\{id\_chapter}\V\|a\E\\{id\_program}\V\|a\E\\{id\_library}){}$%
\5
${}\{{}$\1\6
\&{if} ${}({*}\\{tk}\E\\{string}){}$\5
${}\{{}$\C{ a string should follow }\1\6
\&{while} ${}({*}\\{tk}\E\\{string}){}$\5
${}\{{}$\1\6
${}\\{tk}\K\\{get\_quoted\_name}(\\{tk},\39\\{name});{}$\6
\&{if} ${}(\|a\E\\{id\_chapter}){}$\1\5
${}\\{type}\K\\{dep\_import\_chapter};{}$\2\6
\&{else}\5
${}\{{}$\1\6
\X200:\PB{\\{name}}$\leftarrow$\PB{\\{name}}\.{/}\PB{\\{name}}\X;\6
\&{if} ${}(\|a\E\\{id\_program}){}$\1\5
${}\\{type}\K\\{dep\_import\_program};{}$\2\6
\&{else}\1\5
${}\\{type}\K\\{dep\_import\_library};{}$\2\6
\4${}\}{}$\2\6
${}\\{directly\_depending\_on}(\\{name},\39\\{type},\39\\{exported});{}$\6
\&{if} ${}({*}\\{tk}\E\.{','}){}$\1\5
${}\\{tk}\PP;{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ what?"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ source\ mus}\)\.{t\ be\ chapter,\ progra}\)\.{m\
or\ library"});\2\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Import\ from\ where}\)\.{\ (chapter,\ program\ o}\)\.{r\
library)?"});\2\6
\&{do}\5
${}{*}\\{cp}\PP\K\\{ignore};{}$\5
\&{while} ${}(\\{cp}<\\{tk}){}$;\C{ remove import command from token list }\6
\4${}\}{}$\2\par
\U196.\fi

\N{0}{202}Book file.
Since we want to support both, the book and the non-book style, we have to
look at the given file if it is a book file or an ordinary \.{CWEB} file.
In the latter case, we tangle it as usual. If we find a book file,
we have to do more than the original \.{CTANGLE} did.

\fi

\M{203}References to \.{mcommon.w}.
\Y\B\4\D$\\{longest\_name}$ \5
\T{1000}\par
\B\4\D$\\{long\_buf\_size}$ \5
$(\\{buf\_size}+\\{longest\_name}{}$)\par
\B\4\D$\\{max\_include\_depth}$ \5
\T{10}\par
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{extern} \&{char} \\{buffer}[\\{long\_buf\_size}];\6
\&{extern} \&{char} \\{file\_name}[\\{max\_include\_depth}][\\{max\_file\_name%
\_length}];\6
\&{extern} \&{char} \\{alt\_web\_file\_name}[\\{max\_file\_name\_length}];\6
\&{extern} \&{char} ${}{*}{*}\\{argv\_web},{}$ ${}{*}{*}\\{argv\_change},{}$
${}{*}{*}\\{argv\_out}{}$;\par
\fi

\M{204}
\Y\B\4\D$\\{no\_book}$ \5
\T{0}\par
\B\4\D$\\{book\_program}$ \5
\T{1}\C{ book type }\par
\B\4\D$\\{book\_library}$ \5
\T{2}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} \\{book\_file\_name}[\\{max\_file\_name\_length}];\C{ name of book
file }\6
\&{char} \\{book\_name}[\\{max\_file\_name\_length}];\C{ name of book (no path)
}\6
\&{char} \\{chapter\_name}[\\{max\_file\_name\_length}];\C{ name of current
chapter }\6
\&{extern} \&{char} \\{change\_file\_name}[\\{max\_file\_name\_length}];\6
\&{char} \\{out\_file\_name}[\\{max\_file\_name\_length}];\C{ name of \CEE/
file }\6
\&{char} \\{makefile\_name}[\\{max\_file\_name\_length}];\C{ name of makefile }%
\6
\&{char} \\{book\_dir}[\\{max\_file\_name\_length}];\C{ directory of current
book }\par
\fi

\M{205}Each book can have up to \PB{\\{max\_chapters}} chapters.
For each chapter, we have a couple of dependencies and the name of the
\CEE/ file.
\Y\B\4\D$\\{max\_chapters}$ \5
\T{64}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{chapter\_no};\C{ current chapter number }\6
\&{struct} \\{dependency\_node} ${}{*}\\{chapter\_dep\_head}[\\{max%
\_chapters}];{}$\6
\&{char} ${}{*}\\{ch\_C\_name}[\\{max\_chapters}]{}$;\C{ \CEE/ file name for
each chapter }\par
\fi

\M{206}\.{mCTANGLE} supports both, new \lq book\rq-style
files and the original \.{CWEB} input files. The following section
checks, if the given file is a book or not.

Book files have the file extension \.{prg} or \.{lib}, or the \.{+m} flag set.
If it's a book,
read it to find out which chapters it consists of,
translate all its chapters, create the makefile and \PB{\&{return}}.
If it is an old style \.{CWEB} program, just continue and it
will be translated the same way as \.{CTANGLE} did.
\Y\B\4\X206:Check for book file\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \\{ret\_val}${}\K\T{0},{}$ \\{len}${},{}$ \\{ch};\6
\&{char} ${}{*}\|e,{}$ ${}{*}\\{cp};{}$\7
${}\|e\K\\{getenv}(\.{"DEPDIR"});{}$\6
\&{if} (\|e)\5
${}\{{}$\1\6
${}\\{strcpy}(\\{dep\_dir},\39\|e);{}$\6
${}\\{strcat}(\\{dep\_dir},\39\\{file\_name\_sep\_str}){}$;\C{ ready to add
filename }\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{fatal}(\.{"!\ Environment\ varia}\)\.{ble\ not\ set:"},\39%
\.{"DEPDIR"});{}$\2\6
\X207:Check if we should append \.{.prg} to \PB{\\{file\_name}[\T{0}]}\X;\6
${}\\{len}\K\\{strlen}(\\{file\_name}[\T{0}]);{}$\6
\&{if} ${}(\R\\{strcmp}(\\{file\_name}[\T{0}]+\\{len}-\T{4},\39\.{".prg"})\V%
\\{flags}[\.{'m'}]){}$\5
${}\{{}$\1\6
${}\\{change\_file}\K\NULL;{}$\6
\\{reset\_input}(\,);\6
${}\\{strcpy}(\\{book\_file\_name},\39\\{file\_name}[\T{0}]);{}$\6
\X215:Get book directory\X;\6
\X216:Construct \PB{\\{book\_name}} out of \PB{\\{book\_file\_name}}\X;\6
\X232:Open the book export file\X;\6
\X176:Open dependency file for book\X;\6
\&{if} (\\{show\_progress})\1\5
${}\\{printf}(\.{"Book\ '\%s'\\n"},\39\\{book\_name});{}$\2\6
\X208:Read book file\X;\6
\\{fclose}(\\{file}[\T{0}]);\6
\&{if} (\\{change\_file})\5
${}\{{}$\1\6
\\{fclose}(\\{change\_file});\6
${}\\{change\_file}\K\NULL;{}$\6
\4${}\}{}$\2\6
\X211:Translate all chapters\X;\6
\&{if} ${}({*}\\{makefile\_name}){}$\5
${}\{{}$\1\6
\&{if} (\\{show\_progress})\1\5
${}\\{printf}(\.{"\\nMakefile:\%s\\n"},\39\\{makefile\_name});{}$\2\6
\&{for} ${}(\\{ch}\K\T{0};{}$ ${}\\{ch}<\\{chapter\_no};{}$ ${}\\{ch}\PP){}$\1\5
\\{create\_dependencies}(\\{ch});\2\6
\X240:Create Makefile\X;\6
\4${}\}{}$\2\6
\&{if} ${}(\\{history}>\\{harmless\_message}){}$\1\5
${}\\{ret\_val}\MRL{{\OR}{\K}}\T{1};{}$\2\6
\\{fclose}(\\{book\_dep\_file});\6
\X233:Close the book export file\X;\6
\&{if} (\\{ret\_val})\1\5
\\{printf}(\.{"\\n(Book\ not\ success}\)\.{fully\ translated.)\\n}\)\.{"});\2\6
\&{else} \&{if} (\\{show\_happiness})\1\5
\\{printf}(\.{"\\n(Book\ successfull}\)\.{y\ translated.)\\n"});\2\6
\&{return} \\{ret\_val};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U3.\fi

\M{207}If the web file argument is a file without a file extension, we try
give it \.{.prg}. If this files exists,
\PB{\\{file\_name}[\T{0}]} gets the \.{.prg} extension appended.
\Y\B\4\X207:Check if we should append \.{.prg} to \PB{\\{file\_name}[\T{0}]}%
\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp};{}$\6
\&{FILE} ${}{*}\|f;{}$\7
${}\\{strcpy}(\\{a\_file\_name},\39{*}\\{argv\_web});{}$\6
\&{if} ${}(\R\\{file\_name\_ext}(\\{a\_file\_name})){}$\5
${}\{{}$\C{ if no file extension }\1\6
${}\\{cp}\K\\{a\_file\_name}+\\{strlen}(\\{a\_file\_name});{}$\6
${}\\{strcpy}(\\{cp},\39\.{".prg"});{}$\6
\&{if} ${}((\|f\K\\{fopen}(\\{a\_file\_name},\39\.{"r"}))\I\NULL){}$\5
${}\{{}$\C{ \.{.prg} file exists }\1\6
\\{fclose}(\|f);\6
${}\\{strcpy}(\\{file\_name}[\T{0}],\39\\{a\_file\_name});{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U206.\fi

\M{208}Now we read the book file line by line. We skip everything but commands
introduced by '\.{@}'. All chapters are remembered for later processing.
\Y\B\4\X208:Read book file\X${}\E{}$\6
\&{while} (\\{get\_line}(\,))\5
${}\{{}$\1\6
\&{while} ${}(\\{loc}<\\{limit}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\\{loc}\PP\E\.{'@'}){}$\5
${}\{{}$\1\6
\&{switch} ${}({*}\\{loc}\PP){}$\5
${}\{{}$\1\6
\4\&{case} \.{'@'}:\5
\&{break};\6
\4\&{case} \.{'c'}:\5
\X210:Remember chapter\X;\5
\&{break};\6
\4\&{case} \.{'m'}:\5
\X212:Copy Makefile\X;\5
\&{break};\6
\4\&{default}:\5
\\{err\_print}(\.{"!\ Illegal\ @\ command}\)\.{\ in\ book"});\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U206.\fi

\M{209}When we first scan the book file, we only remember the chapters we have
seen together with optional change and output file names.
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{ch\_web\_name}[\\{max\_chapters}];{}$\6
\&{char} ${}{*}\\{ch\_change\_name}[\\{max\_chapters}];{}$\6
\&{char} ${}{*}\\{ch\_out\_name}[\\{max\_chapters}];{}$\6
\&{int} \\{n\_chapters\_remembered};\par
\fi

\M{210}This is called if we encounter a \.{@c} in a book file.
It stores the chapter name in the arrays defined above.
\Y\B\4\X210:Remember chapter\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp};{}$\7
\&{if} ${}(\\{n\_chapters\_remembered}\G\\{max\_chapters}){}$\1\5
\\{overflow}(\.{"chapters"});\2\6
${}{*}\\{limit}\K\T{0};{}$\6
${}\\{cp}\K\\{get\_name}(\\{loc},\39\\{a\_file\_name});{}$\6
\&{if} (\\{cp})\5
${}\{{}$\1\6
${}\\{loc}\K\\{cp};{}$\6
${}\\{ch\_web\_name}[\\{n\_chapters\_remembered}]\K\\{strmem}(\\{a\_file%
\_name});{}$\6
${}\\{ch\_change\_name}[\\{n\_chapters\_remembered}]\K\NULL;{}$\6
${}\\{ch\_out\_name}[\\{n\_chapters\_remembered}]\K\NULL;{}$\6
${}\\{cp}\K\\{get\_name}(\\{loc},\39\\{a\_file\_name});{}$\6
\&{if} (\\{cp})\5
${}\{{}$\1\6
${}\\{loc}\K\\{cp};{}$\6
${}\\{ch\_change\_name}[\\{n\_chapters\_remembered}]\K\\{strmem}(\\{a\_file%
\_name});{}$\6
${}\\{cp}\K\\{get\_name}(\\{loc},\39\\{a\_file\_name});{}$\6
\&{if} (\\{cp})\5
${}\{{}$\1\6
${}\\{loc}\K\\{cp};{}$\6
${}\\{ch\_out\_name}[\\{n\_chapters\_remembered}]\K\\{strmem}(\\{a\_file%
\_name});{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{n\_chapters\_remembered}\PP;{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
\\{err\_print}(\.{"!\ Chapter\ name\ expe}\)\.{cted"});\2\6
\4${}\}{}$\2\par
\U208.\fi

\M{211}At the end of the book, we translate all chapters we have seen
during the scan.
\Y\B\4\X211:Translate all chapters\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{change\_exists},{}$ ${}{*}\\{out\_exists};{}$\7
\&{for} ${}(\\{chapter\_no}\K\T{0};{}$ ${}\\{chapter\_no}<\\{n\_chapters%
\_remembered};{}$ ${}\\{chapter\_no}\PP){}$\5
${}\{{}$\1\6
\&{if} (\\{show\_progress})\1\5
${}\\{printf}(\.{"\\nChapter\ \%d:"},\39\\{chapter\_no}+\T{1});{}$\2\6
${}\\{strcpy}(\\{chapter\_name},\39\\{book\_dir}){}$;\C{ relative to book
directory }\6
${}\\{strcat}(\\{chapter\_name},\39\\{ch\_web\_name}[\\{chapter\_no}]);{}$\6
${}\\{change\_exists}\K\\{ch\_change\_name}[\\{chapter\_no}];{}$\6
\&{if} (\\{change\_exists})\1\5
${}\\{strcpy}(\\{change\_file\_name},\39\\{change\_exists});{}$\2\6
${}\\{out\_exists}\K\\{ch\_out\_name}[\\{chapter\_no}];{}$\6
\&{if} (\\{out\_exists})\1\5
${}\\{strcpy}(\\{out\_file\_name},\39\\{out\_exists});{}$\2\6
\&{if} (\\{show\_progress})\1\5
${}\\{printf}(\.{"\%s\\n"},\39\\{chapter\_name});{}$\2\6
\X223:Tangle chapter\X;\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U206.\fi

\M{212}The makefile part of the book is copied to a temporary file.
We have to process it after we have tangled all chapters, because
only then we will know all relations and dependencies between them.
While copying the makefile part to a temporary file we automatically
take care of an optional change file.
\Y\B\4\X212:Copy Makefile\X${}\E{}$\6
${}\{{}$\1\6
${}{*}\\{limit}\K\T{0};{}$\6
\&{if} ${}(\R\\{get\_name}(\\{loc},\39\\{makefile\_name})){}$\1\5
${}\\{strcpy}(\\{makefile\_name},\39\.{"Makefile"});{}$\2\6
${}\\{tmp\_makefile}\K\\{tmpfile}(\,);{}$\6
\&{if} ${}(\R\\{tmp\_makefile}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ create\ tem}\)\.{porary\ file\ "},\39\.{"for\
makefile"});{}$\2\6
\&{while} (\\{get\_line}(\,))\5
${}\{{}$\1\6
${}{*}\\{limit}\K\T{0};{}$\6
${}\\{fprintf}(\\{tmp\_makefile},\39\.{"\%s\\n"},\39\\{buffer});{}$\6
\4${}\}{}$\2\6
\\{rewind}(\\{tmp\_makefile});\6
\4${}\}{}$\2\par
\U208.\fi

\M{213}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{strmem}(\,){}$;\par
\fi

\M{214}The following function copies the given string \PB{\|s} to allocated
memory.
\Y\B\&{char} ${}{*}\\{strmem}(\|s){}$\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp}\K\\{malloc}(\\{strlen}(\|s)+\T{1});{}$\7
\&{if} ${}(\R\\{cp}){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory\ for\ str}\)\.{ing\ "},\39\|s);{}$\2\6
\&{return} ${}\\{strcpy}(\\{cp},\39\|s);{}$\6
\4${}\}{}$\2\par
\fi

\M{215}We store the directory part of the book name because we need it
later, since all chapters are searched relative to that.
\Y\B\4\X215:Get book directory\X${}\E{}$\6
$\\{strcpy}(\\{book\_dir},\39\\{book\_file\_name});{}$\6
${}\\{cp}\K\\{file\_name\_part}(\\{book\_dir});{}$\6
${}{*}\\{cp}\K\T{0}{}$;\par
\U206.\fi

\M{216}\PB{\\{book\_name}} is \PB{\\{book\_file\_name}} without \PB{\\{book%
\_dir}} and without
file extension.
\Y\B\4\X216:Construct \PB{\\{book\_name}} out of \PB{\\{book\_file\_name}}\X${}%
\E{}$\6
$\\{cp}\K\\{file\_name\_part}(\\{file\_name}[\T{0}]);{}$\6
${}\\{strcpy}(\\{book\_name},\39\\{cp});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{book\_name});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0}{}$;\2\par
\U206.\fi

\M{217}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{file\_name\_ext}(\,);{}$\6
\&{char} ${}{*}\\{file\_name\_part}(\,);{}$\6
\&{void} \\{to\_parent}(\,);\par
\fi

\M{218}Returns the file name part of path \PB{\|s}. Never returns \PB{$\NULL$}.
Please change the \PB{\\{file\_name\_separator}} for non-\UNIX/ systems.
\Y\B\4\D$\\{file\_name\_separator}$ \5
\.{'/'}\par
\B\4\D$\\{file\_name\_sep\_str}$ \5
\.{"/"}\par
\Y\B\&{char} ${}{*}\\{file\_name\_part}(\|s){}$\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{slash\_pos};{}$\7
${}\\{slash\_pos}\K\\{strrchr}(\|s,\39\\{file\_name\_separator});{}$\6
\&{if} (\\{slash\_pos})\1\5
${}\\{slash\_pos}\PP;{}$\2\6
\&{else}\1\5
${}\\{slash\_pos}\K\|s;{}$\2\6
\&{return} \\{slash\_pos};\6
\4${}\}{}$\2\par
\fi

\M{219}Strips the filename from a full path.
\Y\B\&{void} \\{to\_parent}(\|s)\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp}\K\\{file\_name\_part}(\|s);{}$\7
\&{if} ${}(\\{cp}\E\|s){}$\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
\&{else}\1\5
${}\\{cp}[{-}\T{1}]\K\T{0};{}$\2\6
\4${}\}{}$\2\par
\fi

\M{220}Returns a pointer to the file name extension (e.g.~to \PB{\.{".exp"}})
or \PB{$\NULL$}.
\Y\B\&{char} ${}{*}\\{file\_name\_ext}(\|s){}$\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{return} ${}\\{strrchr}(\\{file\_name\_part}(\|s),\39\.{'.'});{}$\6
\4${}\}{}$\2\par
\fi

\M{221}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{get\_name}(\,){}$;\par
\fi

\M{222}Copies a name from \PB{\\{cp}} to \PB{\\{buffer}}. The name maybe be
optionally quoted
and preceded by white space.
\Y\B\&{char} ${}{*}\\{get\_name}(\\{cp},\39\\{buffer}){}$\1\1\6
\&{char} ${}{*}\\{cp},{}$ ${}{*}\\{buffer};\2\2{}$\6
${}\{{}$\1\6
\&{int} \|i;\7
\&{while} ${}(\\{isspace}({*}\\{cp})){}$\1\5
${}\\{cp}\PP;{}$\2\6
\&{if} ${}({*}\\{cp}\E\.{QUOTE}){}$\5
${}\{{}$\1\6
${}\\{cp}\PP;{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{max\_file\_name\_length};{}$ ${}\|i\PP){}$%
\1\6
\&{if} ${}({*}\\{cp}\E\.{QUOTE}){}$\5
${}\{{}$\1\6
${}{*}\\{buffer}\K\T{0};{}$\6
\&{return} ${}\PP\\{cp};{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
${}{*}\\{buffer}\PP\K{*}\\{cp}\PP;{}$\2\2\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{max\_file\_name\_length};{}$ ${}\|i\PP){}$%
\1\6
\&{if} ${}(\R{*}\\{cp}\V\\{isspace}({*}\\{cp})){}$\5
${}\{{}$\1\6
${}{*}\\{buffer}\K\T{0};{}$\6
\&{if} ${}(\R\|i){}$\1\5
\&{return} \T{0};\2\6
\&{return} \\{cp};\6
\4${}\}{}$\2\6
\&{else}\1\5
${}{*}\\{buffer}\PP\K{*}\\{cp}\PP;{}$\2\2\6
\4${}\}{}$\2\6
${}{*}\\{buffer}\K\T{0};{}$\6
\&{return} \T{0};\6
\4${}\}{}$\2\par
\fi

\M{223}Invokes \.{CTANGLE} on one of its chapters. The name of the chapter to
translate is \PB{\\{chapter\_name}}, its change file is stored in \PB{\\{change%
\_file\_name}}
if \PB{$\\{change\_exists}\I\NULL$}, and the corresponding output file can be
found in
\PB{\\{out\_file\_name}} if \PB{$\\{out\_exists}\I\NULL$}.

We create a new \PB{\\{argv}} with these names and call \PB{\\{tangle\_file}}
to start
the original version of \.{CTANGLE}.
\Y\B\4\X223:Tangle chapter\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|i;\6
\&{char} ${}{*}{*}\\{new\_argv},{}$ ${}{*}{*}\\{argv\_ptr},{}$ ${}{*}\\{cp};{}$%
\6
\&{boolean} \\{retranslate};\6
\&{boolean} \\{has\_exp\_file}${}\K\T{0};{}$\7
${}\\{argc}\K\\{ac};{}$\6
${}\\{new\_argv}\K\\{argv}\K{}$(\&{char} ${}{*}{*}){}$ \\{malloc}${}((\\{argc}+%
\T{3})*{}$\&{sizeof}(\&{char} ${}{*}));{}$\6
\&{if} ${}(\R\\{argv}){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory,\ cannot}\)\.{\ tangle\ "},\39\\{chapter%
\_name});{}$\2\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{argc};{}$ ${}\|i\PP){}$\1\5
${}\\{argv}[\|i]\K\\{av}[\|i];{}$\2\6
${}\\{argv\_ptr}\K\\{argv}+(\\{argv\_web}-\\{av});{}$\6
${}{*}\\{argv\_ptr}\K\\{chapter\_name};{}$\6
\&{if} (\\{argv\_change})\1\5
${}{*}\\{argv\_change}\K\.{"-"};{}$\2\6
${}\\{cp}\K\\{file\_name\_part}(\\{chapter\_name}){}$;\C{ make \CEE/ file name
from chapter name }\6
\&{if} (\\{argv\_out})\1\5
${}{*}\\{argv\_out}\K\\{cp};{}$\2\6
${}\\{ch\_C\_name}[\\{chapter\_no}]\K\\{malloc}(\\{strlen}(\\{cp})+\T{1});{}$\6
\&{if} ${}(\R\\{ch\_C\_name}[\\{chapter\_no}]){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory"},\39\.{"\ for\ C\ file\ name"});{}$\2\6
${}\\{strcpy}(\\{ch\_C\_name}[\\{chapter\_no}],\39\\{cp});{}$\6
\&{if} (\\{change\_exists})\5
${}\{{}$\1\6
\&{if} (\\{argv\_change})\1\5
${}\\{argv\_ptr}\K\\{argv}+(\\{argv\_change}-\\{av});{}$\2\6
\&{else}\1\5
${}\\{argv\_ptr}\K{\AND}\\{argv}[\\{argc}\PP];{}$\2\6
${}{*}\\{argv\_ptr}\K\\{change\_file\_name};{}$\6
\&{if} (\\{out\_exists})\5
${}\{{}$\1\6
\&{if} (\\{argv\_out})\1\5
${}\\{argv\_ptr}\K\\{argv}+(\\{argv\_out}-\\{av});{}$\2\6
\&{else}\1\5
${}\\{argv\_ptr}\K{\AND}\\{argv}[\\{argc}\PP];{}$\2\6
${}{*}\\{argv\_ptr}\K\\{out\_file\_name};{}$\6
${}\\{ch\_C\_name}[\\{chapter\_no}]\K\\{realloc}(\\{ch\_C\_name}[\\{chapter%
\_no}],\39\\{strlen}(\\{out\_file\_name})+\T{1});{}$\6
\&{if} ${}(\R\\{ch\_C\_name}[\\{chapter\_no}]){}$\1\5
${}\\{fatal}(\.{"!\ No\ memory"},\39\.{"\ for\ C\ file\ name"});{}$\2\6
${}\\{strcpy}(\\{ch\_C\_name}[\\{chapter\_no}],\39\\{out\_file\_name}){}$;\C{
override \CEE/ file name }\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\\{fprintf}(\\{book\_dep\_file},\39\.{"\%s\\n"},\39\\{chapter\_name});{}$\6
\X226:Retranslation of chapter necessary? $\rightarrow$ \PB{\\{retranslate}}\X;%
\6
${}\\{history}\K\T{0};{}$\6
\&{if} (\\{retranslate})\5
${}\{{}$\1\6
\X227:Open representation file for writing and write change file name\X\6
${}\\{ret\_val}\MRL{{\OR}{\K}}\\{tangle\_file}(\,){}$;\C{ tangle it with these
arguments }\6
\X228:Close representation file\X;\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} (\\{has\_exp\_file})\5
${}\{{}$\C{ it has an export file, include it in book export file }\1\6
\&{char} ${}{*}\\{cp}\K\\{exp\_file\_name\_of}(\\{a\_file\_name},\39\\{chapter%
\_name},\39\.{".exp"});{}$\7
${}\\{fprintf}(\\{book\_exp\_file},\39\.{"\#include\ \\"\%s\\"\\n"},\39%
\\{cp});{}$\6
\4${}\}{}$\2\6
${}\\{rep\_file}\K\NULL;{}$\6
\\{printf}(\.{"(Skipped.)\\n"});\6
\X178:Read dependency file of chapter\X;\6
\4${}\}{}$\2\6
\X177:Write dependency file for chapter\X;\6
\\{free}(\\{new\_argv});\6
\4${}\}{}$\2\par
\U211.\fi

\M{224}
\Y\B\4\X8:Include files\X${}\mathrel+\E{}$\6
\8\#\&{include} \.{<sys/stat.h>}\par
\fi

\M{225}
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{extern} \&{FILE} ${}{*}\\{rep\_file};{}$\6
\&{char} \\{rep\_file\_name}[\\{max\_file\_name\_length}];\par
\fi

\M{226}A chapter only is retranslated if it is really necessary, because
otherwise
the compiler will also recompile the resulting \CEE/ file. This would result
in very bad turnaround times and therefore is unacceptable.

In order to be able to check if we must retranslate our current chapter,
we store the name of its change file and all files included by means of
\.{@i} in a separate file called the representation file.

Our chapter must only be retranslated, if the resulting \CEE/ file is older
than either the corresponding \.{WEB} file, a possibly existing change file
or one of the included files.
If the name of the change file has changed since last retranslation or if
the representation file does not exist yet, we also have to translate the
chapter.
\Y\B\4\X226:Retranslation of chapter necessary? $\rightarrow$ \PB{%
\\{retranslate}}\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp};{}$\6
\&{struct} \\{stat} \\{s\_C}${},{}$ \|s;\7
${}\\{retranslate}\K\T{0}{}$;\C{ assume no retranslation }\6
${}\\{strcpy}(\\{buffer},\39\\{ch\_C\_name}[\\{chapter\_no}]);{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{buffer});{}$\6
\&{if} ${}(\R\\{cp}){}$\1\5
${}\\{strcat}(\\{buffer},\39\.{".c"});{}$\2\6
\&{if} ${}(\\{stat}(\\{buffer},\39{\AND}\\{s\_C})){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
${}\\{strcpy}(\\{buffer},\39\\{chapter\_name});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{buffer});{}$\6
\&{if} ${}(\R\\{cp}){}$\5
${}\{{}$\1\6
${}\\{cp}\K\\{buffer}+\\{strlen}(\\{buffer});{}$\6
${}\\{strcat}(\\{buffer},\39\.{".w"});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{stat}(\\{buffer},\39{\AND}\|s)){}$\5
${}\{{}$\C{ check if \.{CWEB} file is newer than \CEE/ file }\1\6
${}\\{sprintf}(\\{buffer},\39\.{"\%s.web"},\39\\{chapter\_name});{}$\6
\&{if} ${}(\\{stat}(\\{buffer},\39{\AND}\|s)){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ find\ chapt}\)\.{er:\ \%s\\n"},\39\\{chapter%
\_name});{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{s\_C}.\\{st\_mtime}<\|s.\\{st\_mtime}){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{strcat}(\\{buffer},\39\.{".rep"});{}$\6
${}\\{cp}\K\\{file\_name\_part}(\\{buffer});{}$\6
${}\\{strcpy}(\\{rep\_file\_name},\39\\{cp});{}$\6
${}\\{rep\_file}\K\\{fopen}(\\{rep\_file\_name},\39\.{"r"}){}$;\C{ open the
representation file }\6
\&{if} (\\{rep\_file})\5
${}\{{}$\1\6
${}\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39\\{rep\_file});{}$\6
${}\\{cp}\K\\{strrchr}(\\{buffer},\39\.{'\\n'});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
\&{if} ${}(\\{strcmp}(\\{buffer},\39\\{change\_file\_name}){}$)\C{ same change
file? }\1\6
${}\\{retranslate}\K\T{1}{}$;\C{ no }\2\6
\&{if} ${}({*}\\{buffer}\W\\{strcmp}(\\{buffer},\39\.{"-"})\W\\{strcmp}(%
\\{buffer},\39\.{"/dev/null"})){}$\5
${}\{{}$\C{ if given, check if change file is newer }\1\6
\&{if} ${}(\\{stat}(\\{buffer},\39{\AND}\|s)){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
\&{if} ${}(\\{s\_C}.\\{st\_mtime}<\|s.\\{st\_mtime}){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\&{while} ${}(\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39\\{rep%
\_file})){}$\5
${}\{{}$\C{ check if included files are newer }\1\6
${}\\{cp}\K\\{strrchr}(\\{buffer},\39\.{'\\n'});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
\&{if} ${}(\R\\{strcmp}(\\{buffer},\39\.{"*"})){}$\5
${}\{{}$\C{ asterisk in a single line means chapter has export file }\1\6
${}\\{has\_exp\_file}\K\T{1};{}$\6
\&{continue};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{stat}(\\{buffer},\39{\AND}\|s)){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
\&{if} ${}(\\{s\_C}.\\{st\_mtime}<\|s.\\{st\_mtime}){}$\1\5
${}\\{retranslate}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\\{fclose}(\\{rep\_file});\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{retranslate}\K\T{1}{}$;\C{ no representation file }\2\6
\4${}\}{}$\2\par
\U223.\fi

\M{227}If we have decided to retranslate the current chapter, we open the
representation file for writing and already write its first line, which
always contains the change file name. Other lines containing the names of all
files included by means of \.{@i} may follow during translation.
\Y\B\4\X227:Open representation file for writing and write change file name%
\X${}\E{}$\6
${}\{{}$\1\6
${}\\{rep\_file}\K\\{fopen}(\\{rep\_file\_name},\39\.{"w"});{}$\6
\&{if} ${}(\R\\{rep\_file}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ open\ repre}\)\.{sentation\ file:\ "},\39\\{rep%
\_file\_name});{}$\2\6
${}\\{fprintf}(\\{rep\_file},\39\.{"\%s\\n"},\39\\{change\_file\_name});{}$\6
\4${}\}{}$\2\par
\U223.\fi

\M{228}
\Y\B\4\X228:Close representation file\X${}\E{}$\6
\&{if} (\\{rep\_file})\5
${}\{{}$\1\6
\&{if} ${}(\\{used\_exports}\AND\\{exp\_export}{}$)\C{ if chapter has an export
file }\1\6
${}\\{fprintf}(\\{rep\_file},\39\.{"*\\n"}){}$;\C{ write an asterisk in
representation file }\2\6
\\{fclose}(\\{rep\_file});\6
${}\\{rep\_file}\K\NULL;{}$\6
\4${}\}{}$\2\par
\U223.\fi

\M{229}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{exp\_file\_name\_of}(\,){}$;\par
\fi

\M{230}Dependency files and export files go to a directory which is composed of
the environment variable \.{DEPDIR}, the \PB{\\{book\_name}} (not \PB{\\{book%
\_file\_name}})
and the file part of \PB{\\{basename}} who gets another \PB{\\{suffix}}.
This file name is returned in \PB{\\{expname}}.

\PB{\\{exp\_file\_name\_of}} returns a pointer to the file name part
after \.{DEPDIR} in \PB{\\{expname}}, thus including the book name and the
file name itself.
\Y\B\&{char} ${}{*}\\{exp\_file\_name\_of}(\\{expname},\39\\{basename},\39%
\\{suffix}){}$\1\1\6
\&{char} ${}{*}\\{expname},{}$ ${}{*}\\{basename},{}$ ${}{*}\\{suffix};\2\2{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{dot},{}$ ${}{*}\\{ret},{}$ ${}{*}\\{cp};{}$\7
${}\\{strcpy}(\\{expname},\39\\{dep\_dir});{}$\6
${}\\{ret}\K\\{expname}+\\{strlen}(\\{expname});{}$\6
${}\\{strcat}(\\{expname},\39\\{book\_name});{}$\6
${}\\{strcat}(\\{expname},\39\\{file\_name\_sep\_str});{}$\6
${}\\{cp}\K\\{file\_name\_part}(\\{basename});{}$\6
${}\\{strcat}(\\{expname},\39\\{cp});{}$\6
${}\\{dot}\K\\{file\_name\_ext}(\\{expname});{}$\6
\&{if} (\\{dot})\1\5
${}{*}\\{dot}\K\T{0};{}$\2\6
${}\\{strcat}(\\{expname},\39\\{suffix});{}$\6
\&{return} \\{ret};\6
\4${}\}{}$\2\par
\fi

\M{231}
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{FILE} ${}{*}\\{book\_exp\_file};{}$\6
\&{char} \\{book\_exp\_file\_name}[\\{max\_file\_name\_length}];\6
\&{char} \\{a\_file\_name}[\\{max\_file\_name\_length}];\par
\fi

\M{232}The book's export file only contains \PB{$\#$ \&{include}} statements
for all
export files created by a chapter of the book.
This makes it possible for other books to import all exported stuff from
this book.
\Y\B\4\X232:Open the book export file\X${}\E{}$\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp};{}$\7
${}\\{cp}\K\\{exp\_file\_name\_of}(\\{book\_exp\_file\_name},\39\\{book\_file%
\_name},\39\.{".\_ex"});{}$\6
${}\\{strcpy}(\\{a\_file\_name},\39\\{book\_exp\_file\_name});{}$\6
\\{to\_parent}(\\{a\_file\_name});\6
\&{if} ${}(\R\\{mkdir}(\\{a\_file\_name},\39\.{S\_IRUSR}\OR\.{S\_IWUSR}\OR\.{S%
\_IXUSR}\OR\.{S\_IRGRP}\OR\.{S\_IXGRP}\OR\.{S\_IROTH}\OR\.{S\_IXOTH})){}$\1\5
${}\\{printf}(\.{"New\ dependency\ dire}\)\.{ctory\ created:\ \%s\\n"},\39\\{a%
\_file\_name});{}$\2\6
${}\\{book\_exp\_file}\K\\{fopen}(\\{book\_exp\_file\_name},\39\.{"w"}){}$;\C{
and open it }\6
\&{if} ${}(\R\\{book\_exp\_file}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ create\ exp}\)\.{ort\ file\ for\ book:"},\39\\{book%
\_exp\_file\_name});{}$\2\6
${}\\{strcpy}(\\{a\_file\_name},\39\\{cp});{}$\6
${}\\{cp}\K\\{file\_name\_ext}(\\{a\_file\_name});{}$\6
\&{if} (\\{cp})\1\5
${}\\{strcpy}(\\{cp},\39\.{".exp"});{}$\2\6
\&{for} ${}(\\{cp}\K\\{a\_file\_name};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\6
\&{if} ${}(\R\\{xisalpha}({*}\\{cp})){}$\1\5
${}{*}\\{cp}\PP\K\.{'\_'};{}$\2\2\6
${}\\{fprintf}(\\{book\_exp\_file},\39\.{"\#ifndef\ \%s\\n\#define}\)\.{\ \%s%
\\n"},\39\\{a\_file\_name},\39\\{a\_file\_name});{}$\6
\4${}\}{}$\2\par
\U206.\fi

\M{233}
\Y\B\4\X233:Close the book export file\X${}\E{}$\6
${}\{{}$\1\6
${}\\{fprintf}(\\{book\_exp\_file},\39\.{"\#endif\\n"});{}$\6
\\{fclose}(\\{book\_exp\_file});\6
${}\\{keep\_exp\_file\_if\_changed}(\.{".exp"},\39\\{book\_exp\_file%
\_name});{}$\6
\4${}\}{}$\2\par
\U206.\fi

\M{234}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{chapter\_to\_book\_exp}(\,);\par
\fi

\M{235}The book export file contains \PB{$\#$ \&{include}}s for all export
files created
by one of the book's chapters. The following function outputs the \PB{$\#$ %
\&{include}}
for the export file of the current chapter \PB{\\{file\_name}[\T{0}]}.
\Y\B\&{void} \\{chapter\_to\_book\_exp}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{char} ${}{*}\\{cp}\K\\{exp\_file\_name\_of}(\\{a\_file\_name},\39\\{file%
\_name}[\T{0}],\39\.{".exp"});{}$\7
${}\\{fprintf}(\\{book\_exp\_file},\39\.{"\#include\ \\"\%s\\"\\n"},\39%
\\{cp}){}$;\C{ write the \PB{$\#$ \&{include}} }\6
\4${}\}{}$\2\par
\fi

\N{2}{236}Makefile.
The last part of the book file is the \.{makefile}.
It is copied literally from the book file to \PB{\\{makefile\_name}}.
In order to support dependencies between the current book and other books
and inside the book inself, we insert some constants in the header of
the \.{makefile}.
\bigskip
\item{$\bullet$}\PB{\.{CHAPTERS}} contains all chapters of the current book
with the extension \.{".o"}.
\item{$\bullet$}\PB{\.{LIBRARIES}} contains all libraries our book imports
from.
Each library is preceded by \PB{\.{LIBPREFIX}} which you can define in the
makefile part.
\item{$\bullet$}For each chapter a similar named constant
(all characters that are not allowed are replaced by \PB{\.{'\_'}})
which contains all files this particular chapter depends on.

\fi

\M{237}
\Y\B\4\D$\\{max\_col}$ \5
\T{78}\par
\Y\B\4\X19:Global variables\X${}\mathrel+\E{}$\6
\&{FILE} ${}{*}\\{make\_file},{}$ ${}{*}\\{tmp\_makefile};{}$\6
\&{int} \\{make\_col};\C{ column in makefile }\par
\fi

\M{238}
\Y\B\4\X2:Predeclaration of procedures\X${}\mathrel+\E{}$\6
\&{void} \\{mf\_print}(\,);\par
\fi

\M{239}We write these constants into the \.{makefile} until we read the
\PB{\\{max\_col}} column. The following function writes a string \PB{\|s} which
is preceded by \PB{\\{prefix}} and whose extension is replaced by \PB{\\{ext}}.
If it doesn't fit on the current line, a backslash and a newline
are output and we restart on column~1 of the next line.
\Y\B\&{void} ${}\\{mf\_print}(\\{prefix},\39\|s,\39\\{ext}){}$\1\1\6
\&{char} ${}{*}\\{prefix},{}$ ${}{*}\|s,{}$ ${}{*}\\{ext};\2\2{}$\6
${}\{{}$\1\6
\&{int} \\{slen};\6
\&{char} ${}{*}\\{cp};{}$\7
\&{if} (\\{prefix})\1\5
${}\\{strcpy}(\\{buffer},\39\\{prefix});{}$\2\6
\&{else}\1\5
${}{*}\\{buffer}\K\T{0};{}$\2\6
${}\\{strcat}(\\{buffer},\39\|s);{}$\6
\&{if} (\\{ext})\5
${}\{{}$\1\6
${}\\{cp}\K\\{file\_name\_ext}(\\{buffer});{}$\6
\&{if} (\\{cp})\1\5
${}{*}\\{cp}\K\T{0};{}$\2\6
${}\\{strcat}(\\{buffer},\39\\{ext});{}$\6
\4${}\}{}$\2\6
${}\\{slen}\K\\{strlen}(\\{buffer});{}$\6
${}\\{make\_col}\MRL{+{\K}}\\{slen};{}$\6
\&{if} ${}(\\{make\_col}\G\\{max\_col}){}$\5
${}\{{}$\1\6
${}\\{fprintf}(\\{make\_file},\39\.{"\\\\\\n\%s"},\39\\{buffer});{}$\6
${}\\{make\_col}\K\\{slen};{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{fprintf}(\\{make\_file},\39\\{buffer});{}$\2\6
\4${}\}{}$\2\par
\fi

\M{240}Ok, now we create the \.{makefile}. First we open it, then we
write some helpful constants and finally we append the rest of the
book file.
\Y\B\4\X240:Create Makefile\X${}\E{}$\6
${}\{{}$\1\6
\&{int} \|i;\7
${}\\{make\_col}\K\T{0};{}$\6
${}\\{make\_file}\K\\{fopen}(\\{makefile\_name},\39\.{"w"});{}$\6
\&{if} ${}(\R\\{make\_file}){}$\1\5
${}\\{fatal}(\.{"!\ Cannot\ create\ mak}\)\.{efile\ "},\39\\{makefile%
\_name});{}$\2\6
\X241:Output \.{CHAPTERS} makefile constant\X;\6
\&{if} (\\{books\_head})\1\5
\X242:Output \.{LIBRARIES} makefile constant\X;\2\6
\X243:Output makefile constant for each chapter\X;\6
\&{while} ${}(\\{fgets}(\\{buffer},\39{}$\&{sizeof} (\\{buffer})${},\39\\{tmp%
\_makefile})){}$\1\5
${}\\{fprintf}(\\{make\_file},\39\.{"\%s"},\39\\{buffer});{}$\2\6
\\{fclose}(\\{make\_file});\6
\\{fclose}(\\{tmp\_makefile});\6
\4${}\}{}$\2\par
\U206.\fi

\M{241}All chapters get an \PB{\.{".o"}} extension.
\Y\B\4\X241:Output \.{CHAPTERS} makefile constant\X${}\E{}$\6
${}\{{}$\1\6
${}\\{mf\_print}(\NULL,\39\.{"CHAPTERS="},\39\NULL);{}$\6
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{chapter\_no};{}$ ${}\|i\PP){}$\1\5
${}\\{mf\_print}(\.{"\ "},\39\\{ch\_C\_name}[\|i],\39\.{".o"});{}$\2\6
${}\\{fprintf}(\\{make\_file},\39\.{"\\n"});{}$\6
${}\\{make\_col}\K\T{0};{}$\6
\4${}\}{}$\2\par
\U240.\fi

\M{242}Libraries get their path stripped off and are preceded by \.{%
\$(LIBPREFIX)}.
\Y\B\4\X242:Output \.{LIBRARIES} makefile constant\X${}\E{}$\6
${}\{{}$\1\6
\&{struct} \\{book\_node} ${}{*}\\{bn};{}$\6
\&{char} ${}{*}\\{cp};{}$\7
${}\\{mf\_print}(\NULL,\39\.{"LIBRARIES="},\39\NULL);{}$\6
\&{for} ${}(\\{bn}\K\\{books\_head};{}$ \\{bn}; ${}\\{bn}\K\\{bn}\MG%
\\{next}){}$\1\6
\&{if} ${}(\\{bn}\MG\\{type}\E\\{book\_library}){}$\5
${}\{{}$\1\6
${}\\{cp}\K\\{file\_name\_part}(\\{bn}\MG\\{name});{}$\6
${}\\{mf\_print}(\.{"\ \$(LIBPREFIX)"},\39\\{cp},\39\.{""});{}$\6
\4${}\}{}$\2\2\6
${}\\{fprintf}(\\{make\_file},\39\.{"\\n"});{}$\6
${}\\{make\_col}\K\T{0};{}$\6
\4${}\}{}$\2\par
\U240.\fi

\M{243}The dependencies of each chapter have already been collected at the
end of phase two (by a call to \PB{\\{create\_dependencies}}). The dependencies
for
chapter $i$ can be found in \PB{\\{ch\_make\_dep}[\|i]}.
\Y\B\4\X243:Output makefile constant for each chapter\X${}\E{}$\6
${}\{{}$\1\6
\&{struct} \\{make\_dep} ${}{*}\\{md};{}$\6
\&{char} ${}{*}\\{cp};{}$\7
\&{for} ${}(\|i\K\T{0};{}$ ${}\|i<\\{chapter\_no};{}$ ${}\|i\PP){}$\5
${}\{{}$\1\6
${}\\{strcpy}(\\{buffer},\39\\{ch\_web\_name}[\|i]){}$;\C{ convert to makefile
constant }\6
\&{for} ${}(\\{cp}\K\\{buffer};{}$ ${}{*}\\{cp};{}$ ${}\\{cp}\PP){}$\1\6
\&{if} ${}(\R\\{isalnum}({*}\\{cp})){}$\1\5
${}{*}\\{cp}\K\.{'\_'};{}$\2\6
\&{else} \&{if} ${}(\\{islower}({*}\\{cp})){}$\1\5
${}{*}\\{cp}\K\\{toupper}({*}\\{cp});{}$\2\2\6
${}\\{mf\_print}(\\{buffer},\39\.{"="},\39\NULL);{}$\6
\&{if} ${}(\\{strchr}(\\{ch\_C\_name}[\|i],\39\.{'.'})){}$\1\5
${}\\{mf\_print}(\NULL,\39\\{ch\_C\_name}[\|i],\39\NULL);{}$\2\6
\&{else}\1\5
${}\\{mf\_print}(\NULL,\39\\{ch\_C\_name}[\|i],\39\.{".c"});{}$\2\6
\&{for} ${}(\\{md}\K\\{ch\_make\_dep}[\|i];{}$ \\{md}; ${}\\{md}\K\\{md}\MG%
\\{next}){}$\1\5
${}\\{mf\_print}(\.{"\ "},\39\\{md}\MG\\{name},\39\NULL);{}$\2\6
${}\\{fprintf}(\\{make\_file},\39\.{"\\n"});{}$\6
${}\\{make\_col}\K\T{0};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U240.\fi

\M{244}
\Y\B\4\D$\.{QUOTE}$ \5
\.{'\\"'}\par
\fi

\N{0}{245}Index.
Here is a cross-reference table for \.{mCTANGLE}.
All sections in which an identifier is
used are listed with that identifier, except that reserved words are
indexed only when they appear in format definitions, and the appearances
of identifiers in section names are not indexed. Underlined entries
correspond to where the identifier was declared. Error messages and
a few other things like ``ASCII code dependencies'' are indexed here too.
\fi


\inx
\fin
\con\end
