summaryrefslogtreecommitdiff
path: root/macros/latex209/contrib/misc/db.sty
blob: 983152823f60fa465b3e4b23b295a2ba8855a5bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236

%%%%%%%%%%%%%%%  DATABASE STYLE  %%%%%%%%%%%%%%%%%%

% db.sty
%
% Style to generate listings, to send out letters, etc.  using
% a database.
%
% Version 2.1 (11/20/91)
%
% Written by George Panagopoulos (georgios@umiacs.umd.edu)

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

\long\def\DOCCOMMENT#1\ENDDOCCOMMENT{}

\DOCCOMMENT

%%%%%%%%%%%%  SAMPLE DATABASE FILE mydb.tdb:

% Schema definition

\fields{FName, LName, 
        Email, Addr, 
        local} 

% Database

\tuple{FName=	George,
       LName=	Panagopoulos,
       Addr=	{CS Dept., U of MD, College Park 20742},
       Email=	{\tt georgios@umiacs.umd.edu},
       local=	1}

\tuple{FName=	Somebody,
       LName=	Else,
       Email=	{\tt sb@elsewhere}} % all other fields empty

\tuple{FName=	Ten,
       LName=	\FirstName}

%%%%%%%%%%%%%  SAMPLE USE FILE mydb.tex:

\documentstyle[db]{article}

\begin{document}

% List 1

\newcommand{\tupletext}{\thetuplectr & \FName\ \LName & \Email \\} 
\begin{tabular}{rll}
  \db{mydb} % Lists all
\end{tabular}
===
\thetuplectr\ person(s) listed

% List 2

\renewcommand{\tupletext}{\FName\ (\Email)} 
\ref{num:tuples} local person(s):

\begin{enumerate}
  \db{mydb}[local] % lists all that have nonempty \local
  \label{num:tuples} 
\end{enumerate}

\end{document}

%%%%%%%%%%%%%  OUTPUT of mydb.tex:

1 George Panagopoulos  georgios@umiacs.umd.edu
2 Somebody Else        sb@elsewhere
3 Ten Ten
===
3 person(s) listed

1 person(s) below:

1. George (georgios@umiacs.umd.edu)

%%%%%%%%%%%%%% NOTES (refer to example above)

Database files have the extension ".tdb".

Field order is irrelevant.

A subset of the fields may be given as argument in the \tuple command.
The rest become empty.

TeX/LaTeX commands are valid inside field values.

Other fields are valid inside field values. 

A field value must not contain a comma, unless the comma is enclosed
in braces.
                     
White space is insignificant outside \fields and \tuple commands in
the database file.

White space is insignificant inside a \fields or a \tuple command,
except between the first letter of a field name and the following
equal sign, and between the first letter of a field value and the
following comma or closing brace.  
Therefore: 
  In a \fields command, *there must be no space between the field name
    and the following comma or closing brace*: 
      \fields{ Name, Addr} 
    is valid, but
      \fields{Name ,Addr} 
    is invalid, and so is 
      \fields{Name,Addr } 
  In a \tuple command, *there must be no space between the field name
    and the equal sign, and no unwanted spaces between the field value
    and the following comma or closing brace*:
      \tuple{ Name= x xx , Addr= yy y } 
    is equivalent to
      \tuple{Name={x xx },Addr={yy y }}, 
    but
      \tuple{Name =xxx,Addr=yyy} 
    is invalid.

Beware of conflicts between field names and other TeX macros. The 
\fields command issues a warning if your field name conflicts with an
already defined macro, but goes on to redefine it anyway.

The field macros become undefined after the execution of the the \db
command. The old values (if applicable) are NOT restored.

The same database and more than one databases may be included in the
same document.

The counter {tuplectr} is used to count tuples. The macro \thetuplectr
may be used and/or modified at wish. The value of the counter is saved
in the \ref variable in the end of the \db command. 

\ENDDOCCOMMENT

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

\newcounter{tuplectr}

%%%%%%%%%%%% USEFUL MACROS

\def\ignorewhitespace{\catcode`\ =9\catcode`\^^M=9}
\def\noignorewhitespace{\catcode`\ =10\catcode`\^^M=5}

\ignorewhitespace

\def\db@ifb#1{ % trim one space from #1, if needed
  \ifx \space #1
     \else #1 \fi}

%%%%%%%%%%%% SCHEMA READING

\def\chk@fld@name#1{ % check fldname #1 for conflict with other macros
   \expandafter\ifx \csname#1\endcsname \relax % if undefined
     \else
       \global\expandafter\let\csname#1\endcsname\relax % undefine macro
       \typeout{Warning: \space field \space name \space 
                \expandafter\string\csname#1\endcsname 
                \space redefines \space a \space TeX \space macro} 
     \fi}

\def\@field#1,{ % expand \init@fields with: \gdef\#1{} (#1=fldname)
                % and \undef@fields with: \global\let\#1\relax
   \edef\fld@name{\db@ifb#1}
   \chk@fld@name{\fld@name}
   \xdef\init@fields{
       \init@fields
       \expandafter\gdef\csname\fld@name\endcsname{}}
   \xdef\undef@fields{
       \undef@fields
       \global\expandafter\let\csname\fld@name\endcsname\relax}}

\def\parse@fld@names#1{ % set \init@fields to clear all fields
                        % and \undef@fields to undef all field macros
   \@for\@args:=#1
       \do {\expandafter\@field\@args,}}

\def\fields#1{ % read field names (keeps ignoring whitespace)
   \xdef\init@fields{}
   \xdef\undef@fields{}
   \parse@fld@names{#1}}

%%%%%%%%%%%% TUPLE PARSING

\def\@setfield#1=#2,{
     \expandafter\xdef\csname\db@ifb#1\endcsname{#2}}

\def\parse@fields#1{
   \@for\@args:=#1
       \do {\expandafter\@setfield\@args,}}

\def\print@tuple{ % print tuple value as requested
   % \db@flag is not expanded and contains the name of a field
   \edef\db@flag@val{\db@flag} % eval \db@flag
   \ifx \db@flag@val \empty % ignore tuple if \db@flag=\empty
      \else 
         \refstepcounter{tuplectr}
         \tupletext
   \fi}

%%%%%%%%%%%% TUPLE READING

\def\@tuple#1{ % parse tuple and call \print@tuple
   \init@fields % empty field values
   \parse@fields{#1}
   \print@tuple
   \ignorewhitespace}

\def\tuple{ % read tuple, print \tupletext if \db@flag not empty
   \noignorewhitespace % will be restored by \@tuple
   \@tuple}

\def\notuple#1{} % ignore entry

%%%%%%%%%%%% DB READING

\def\@db#1[#2]{ % #1=file, #2=field not to be empty for \tupletext
  \ifx . #2
       \gdef\db@flag{1} % always nonempty
     \else
       \xdef\db@flag{\csname#2\endcsname}
     \fi
  \setcounter{tuplectr}{0}
  \ignorewhitespace
  \@input{#1.tdb}
  \undef@fields
  \noignorewhitespace}

\def\db#1{ % read database, print \tupletext for each included tuple
  \@ifnextchar [
      {\@db#1}
      {\@db#1[.]}}

\noignorewhitespace