\ifx\STYLEDEF\relax\endinput\else\let\STYLEDEF=\relax\fi % \input only once
%
% styledef.tex: Macros to selectively input parts of a file.
% version: 1.0  release: 16 April 1991
%
% copyright (c) 1991 Marcel R. van der Goot
%	You can use these macros to typeset documents. You may
%	distribute this file freely, provided that you also distribute
%	the accompanying documentation.
%	    You may make changes to this file, or extract portions
%	of it for inclusion in other files, provided that
%	    (1) you change the name of the file;
%	    (2) you give proper credit and include copyright
%		information where applicable;
%	    (3) explain how an unchanged version can be obtained; and
%	    (4) document the usage of your macros/changes (if usage
%		of your macros is not worth documenting, they must not
%		be worth using).
%	You are not allowed to use the name ``Midnight Macros'' for
%	any changed files.
%	    The above rules for making changes do not apply where it
%	is explicitly noted in this file that something can be changed
%	to conform to your local installation.
%
% USAGE:
%   See the file styledef.doc.
%   You need Midnight/dolines.tex and Midnight/loop.tex to use these macros.
%
% original: csvax.cs.caltech.edu [131.215.131.131] in pub/tex
%	    (use anonymous ftp). Also in various archives.
%
% Caltech, Pasadena  ---  Marcel van der Goot
%			  marcel@cs.caltech.edu
%			    Caltech 256--80
%			    Pasadena, CA 91125
%			    USA
%			    (818) 356--4603
%

% update history:
% version 1.0: This one.
%	release 16 April 1991: the original (this one)
%

%%%%%% CODE: (you don't need to read this to use the macros)

\edef\next{\the\catcode`\_} % to remember that catcode
\catcode`\_=11 % 11=letter (for private macros)

%%%%%%%%%%%%%%%%%%%% the current style list
% A style list is represented by a token register. The register is either
% empty or contains a sequence of words separated by single commas (no spaces).
% A non-empty list starts with a comma. A list denotation is a list of words
% separated by commas and spaces.
% \setstyle#1#2. makes style list reg #1 equal to #2 (a list denotation),
% \addstyle#1#2. adds the list #2 to the list register #1.

\let\newstyle=\newtoks

\def\setstyle#1#2% #1 a token reg, #2 a list denotation
   {#1={}%
    \make_stylelist#1#2 .% space before the dot
   }

\def\addstyle#1#2% #1 a token reg, #2 a list denotation
   {\make_stylelist#1#2 .% space before the dot
   }

%%%%%%%%%%%%%%%%%%%% reading a style list denotation
% \make_stylelist takes as first argument the name of a token register.
% Following that name there should be a list of words separated by spaces
% and/or commas, terminated by ` .' (a space and a dot). It constructs
% the corresponding style list in #1.
% \make_stylelist takes the sequence up till the first space, calls
% \nocomma_stylelist with that sequence, and recurses with the sequence after
% the first space. \nocomma_stylelist works similarly, but strips a comma
% rather than a space. (Note: separation by single commas without spaces
% is slightly more efficient.)

\def\eat_style#1.{} % skip everything till first dot

\def\make_stylelist#1#2 #3.% #1=name of list; #2#3=list ending in ` .'
   {\if.#2.\else\nocomma_stylelist#1#2,.\fi
    \if.#3.\let\style_tmp=\eat_style
    \else\let\style_tmp=\make_stylelist
    \fi
    \style_tmp#1#3.%
   }

\def\nocomma_stylelist#1#2,#3.% #1=name of list; #2#3=list ending in `,.'
   {\if.#2.\else#1=\expandafter{\the#1,#2}\fi
    \if.#3.\let\style_tmp=\eat_style
    \else\let\style_tmp=\nocomma_stylelist
    \fi
    \style_tmp#1#3.%
   }

%%%%%%%%%%%%%%%%%%%% determining whether lists intersect
% \isect_style is used to check whether two lists have a non-empty
% intersection. The switch \if_style will be set to indicate whether
% the lists intersect.
% \style_member takes two arguments, a style list register and a word.
% It sets the switch if the word is in the style list. This check is done
% by TeX's pattern match mechanism rather than through word-by-word comparison:
% To check for the presence of word `xyz' a macro `\style_tmp#1,xyz,#2.' is
% defined. If it is called as `\style_tmp<list>,xyz,.' where <list> is the
% contents of the style list, then #2 will not be empty if and only if the
% pattern `,xyz,' is part of <list>, i.e., iff `xyz' is in the list.
% \doisect_style calls \style_member repeatedly for each word in the second
% list.

\newif\if_style

\def\style_member#1#2% #1 a style list (token reg), #2 a word
   {\def\style_tmp##1,#2,##2.{\check_style{##2}}%
    \expandafter\style_tmp\the#1,#2,.%
   }

\def\check_style#1% check whether #1 is empty
   {\if.#1.\else\_styletrue\fi
   }

\def\doisect_style#1,#2,#3.%  #1=reg, #2#3=expansion of list reg ending in ,.
   {\if.#2.\else\style_member#1{#2}\fi
    \if_style\let\style_tmp=\eat_style
    \else\if.#3.\let\style_tmp=\eat_style
         \else\let\style_tmp=\doisect_style
    \fi  \fi
    \style_tmp#1,#3.%
   }

\def\isect_style#1#2% two list regs
   {\_stylefalse
    \expandafter\doisect_style\expandafter#1\the#2,,.% extra comma for #2={}
   }

%%%%%%%%%%%%%%%%%%%% including a style
% \readstyle takes a style list register and a filename. It puts the style list
% in \style_list, then inputs the file.
% \skip_style skips everything till the next \endstyle. It uses
% dolines.tex to read the input line-by-line. To make that possible,
% the grouping characters are disabled (because they must balance on a line),
% the comment char is disabled (because it causes wraparound), the argument
% character is disabled (because a macro is defined that has the line as
% body --- it should not have undeclared arguments in the body), and the
% escape character is disabled (not to prevent expansion, but to prevent lines
% containing an `outer' control sequence). Note: If you wanted a real
% ``comment environment,'' you should set all catcodes of all characters to
% 11 or 12.
% \styledef and \negstyledef have list denotations as arguments. They create
% a list \style_other, then skip based on the intersection of \style_other
% and \style_list. If no skip is done, \endstyle is equivalent to \relax.
% \savereadstyle and \setreadstyle serve to access the protected \style_list
% register.

\input Midnight/dolines

\newtoks\style_list
\newtoks\style_other

\def\readstyle#1#2% #1 a token reg, #2 a filename
   {\style_list=#1%
    \input#2 % significant space (sometimes)
   }

\def\savereadstyle#1% a style (token) reg
   {#1=\style_list}

\def\setreadstyle#1% a style reg
   {\style_list=#1}

{\catcode`\/=0 /catcode`/\=12 % see dolines.doc
 /gdef/end_style{\endstyle}
}

\let\endstyle=\relax

\def\skip_style
   {\begingroup
    \let\beforelines=\relax
    \let\afterlines=\relax
    \def\everyline##1{}%
    \let\enddolines=\end_style
    \let\finishdolines=\endgroup
    \catcode`\{=12 \catcode`\}=12 \catcode`\%=12
    \catcode`\#=12 \catcode`\\=12
    \begindolines
   }

\def\styledef#1% #1 a list denotation
   {\style_other={}%
    \make_stylelist\style_other#1 .% space before dot
    \isect_style\style_list\style_other
    \if_style
    \else\expandafter\skip_style
    \fi
   }

\def\negstyledef#1% #1 a list denotation
   {\style_other={}%
    \make_stylelist\style_other#1 .% space before dot
    \isect_style\style_list\style_other
    \if_style\expandafter\skip_style\fi
   }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\catcode`\_=\next
