summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/LICENSE356
-rw-r--r--src/hdb/README154
-rw-r--r--src/hdb/buffer.h38
-rw-r--r--src/hdb/comp.cc78
-rw-r--r--src/hdb/cvt.cc83
-rw-r--r--src/hdb/db.cc276
-rw-r--r--src/hdb/db.h129
-rw-r--r--src/hdb/filemap.cc302
-rw-r--r--src/hdb/filemap.h196
-rw-r--r--src/hdb/hdbcvt.cc50
-rw-r--r--src/hdb/hdbfix.cc140
-rw-r--r--src/hdb/hdbtest.cc153
-rw-r--r--src/hdb/sortable.cc81
-rw-r--r--src/hdb/sortable.h138
-rw-r--r--src/hdb/test.cc52
-rw-r--r--src/hed/edit.cc262
-rw-r--r--src/hed/edit.h61
-rw-r--r--src/hed/hed.cc56
-rw-r--r--src/hed/input.cc107
-rw-r--r--src/hed/input.h52
-rw-r--r--src/hed/tables.cc442
-rw-r--r--src/hed/tables.h61
-rw-r--r--src/hed/test.cc33
-rw-r--r--src/http/http.h144
-rw-r--r--src/http/mime.cc92
-rw-r--r--src/http/mime.h99
-rw-r--r--src/http/req.cc100
-rw-r--r--src/http/resp.cc79
-rw-r--r--src/http/test.cc28
-rw-r--r--src/labat/README49
-rw-r--r--src/labat/adensin.dat0
-rw-r--r--src/labat/adensout.dat402
-rw-r--r--src/labat/apotin.dat0
-rw-r--r--src/labat/apotout.dat402
-rw-r--r--src/labat/aprtout.dat1175
-rw-r--r--src/labat/atomctrl.dat15
-rw-r--r--src/labat/atomdens.dat401
-rw-r--r--src/labat/atomlab.cc187
-rw-r--r--src/labat/deriv.f65
-rw-r--r--src/labat/exchen.f21
-rw-r--r--src/labat/exchpt.f33
-rw-r--r--src/labat/gcor.f15
-rw-r--r--src/labat/gga.f45
-rw-r--r--src/labat/ggaec.f43
-rw-r--r--src/labat/ggaexc.f76
-rw-r--r--src/labat/ggauc.f96
-rw-r--r--src/labat/ggauxc.f82
-rw-r--r--src/labat/grabgr.f32
-rw-r--r--src/labat/grad.f26
-rw-r--r--src/labat/labat.f587
-rw-r--r--src/labat/laplac.f41
-rw-r--r--src/labat/laplac2.f11
-rw-r--r--src/labat/ldaec.f21
-rw-r--r--src/labat/ldauc.f32
-rw-r--r--src/labat/resten.f634
-rw-r--r--src/labat/spline.f34
-rw-r--r--src/labat/splint.f37
-rw-r--r--src/lang/basic.cc315
-rw-r--r--src/lang/db.cc237
-rw-r--r--src/lang/env.cc308
-rw-r--r--src/lang/env.h156
-rw-r--r--src/lang/flow.cc198
-rw-r--r--src/lang/func.cc249
-rw-r--r--src/lang/help.cc140
-rw-r--r--src/lang/lang.cc39
-rw-r--r--src/lang/latex.cc152
-rw-r--r--src/lang/ops.cc150
-rw-r--r--src/lang/parse.cc453
-rw-r--r--src/lang/test.cc45
-rw-r--r--src/lang/token.cc268
-rw-r--r--src/lang/token.h230
-rw-r--r--src/mail/inbox.cc36
-rw-r--r--src/mail/list.cc52
-rw-r--r--src/mail/move.cc60
-rw-r--r--src/mail/res.h30
-rw-r--r--src/makefile177
-rw-r--r--src/mime/base64.cc132
-rw-r--r--src/mime/def.cc149
-rw-r--r--src/mime/enc.h36
-rw-r--r--src/mime/mailbox.cc137
-rw-r--r--src/mime/mailbox.h60
-rw-r--r--src/mime/mime.cc188
-rw-r--r--src/mime/mime.h99
-rw-r--r--src/mime/pack.cc143
-rw-r--r--src/mime/pack.h48
-rw-r--r--src/mime/qp.cc150
-rw-r--r--src/mime/test.cc108
-rw-r--r--src/mt/cfind.f80
-rw-r--r--src/mt/charset.h131
-rw-r--r--src/mt/config.cc33
-rw-r--r--src/mt/config.h27
-rw-r--r--src/mt/crfind.f80
-rw-r--r--src/mt/dates.cc207
-rw-r--r--src/mt/dates.h49
-rw-r--r--src/mt/find_not_of.f80
-rw-r--r--src/mt/find_of.f80
-rw-r--r--src/mt/issue.cc51
-rw-r--r--src/mt/issue.h55
-rw-r--r--src/mt/lock.cc114
-rw-r--r--src/mt/lock.h72
-rw-r--r--src/mt/lookup.cc88
-rw-r--r--src/mt/lookup.h32
-rw-r--r--src/mt/mlock.h48
-rw-r--r--src/mt/mread.cc135
-rw-r--r--src/mt/mread.h63
-rw-r--r--src/mt/mset.cc81
-rw-r--r--src/mt/mset.h62
-rw-r--r--src/mt/msmap.cc84
-rw-r--r--src/mt/msmap.h89
-rw-r--r--src/mt/mstream.cc72
-rw-r--r--src/mt/mstream.h103
-rw-r--r--src/mt/mstring.cc139
-rw-r--r--src/mt/mstring.h222
-rw-r--r--src/mt/mvec.h149
-rw-r--r--src/mt/qran.h34
-rw-r--r--src/mt/random.cc95
-rw-r--r--src/mt/random.h39
-rw-r--r--src/mt/rfind_not_of.f80
-rw-r--r--src/mt/rfind_of.f80
-rw-r--r--src/mt/scomptab.f44
-rw-r--r--src/mt/sconvert.f35
-rw-r--r--src/mt/sfind.f40
-rw-r--r--src/mt/sfindtab.f40
-rw-r--r--src/mt/skip_parentesis.f42
-rw-r--r--src/mt/split.h72
-rw-r--r--src/mt/srfind.f40
-rw-r--r--src/mt/srfindtab.f40
-rw-r--r--src/mt/stackque.h64
-rw-r--r--src/mt/stringref.cc126
-rw-r--r--src/mt/stringref.h239
-rw-r--r--src/mt/strip.f31
-rw-r--r--src/mt/test.cc337
-rw-r--r--src/mt/uniheap.h65
-rw-r--r--src/net/htcd.cc153
-rw-r--r--src/net/isocket.cc58
-rw-r--r--src/net/isocket.h68
-rw-r--r--src/net/redirect.cc185
-rw-r--r--src/net/route80.cc64
-rw-r--r--src/net/server.cc75
-rw-r--r--src/net/server.h46
-rw-r--r--src/net/test.cc44
-rw-r--r--src/net/thrserv.cc255
-rw-r--r--src/net/thrserv.h79
-rw-r--r--src/ops/basic.cc269
-rw-r--r--src/ops/comp.cc134
-rw-r--r--src/ops/express.cc173
-rw-r--r--src/ops/express.h79
-rw-r--r--src/ops/latex.cc101
-rw-r--r--src/ops/nnstyle.h53
-rw-r--r--src/ops/operator.cc44
-rw-r--r--src/ops/operator.h97
-rw-r--r--src/ops/string.cc274
-rw-r--r--src/ops/test.cc161
-rw-r--r--src/serv/auth.cc162
-rw-r--r--src/serv/const.cc69
-rw-r--r--src/serv/direct.cc73
-rw-r--r--src/serv/form.cc102
-rw-r--r--src/serv/htcd.h74
-rw-r--r--src/serv/htcs.cc92
-rw-r--r--src/serv/main.cc122
-rw-r--r--src/serv/request.cc279
-rw-r--r--src/serv/tempmap.cc82
-rw-r--r--src/serv/tempmap.h57
-rw-r--r--src/sh/convert.cc376
-rw-r--r--src/sh/dates.cc138
-rw-r--r--src/sh/file.cc367
-rw-r--r--src/sh/htc.cc92
-rw-r--r--src/sh/htc.h77
-rw-r--r--src/sh/main.cc129
-rw-r--r--src/sh/net.cc122
-rw-r--r--src/sh/string.cc32
-rw-r--r--src/sh/sys.cc152
-rw-r--r--src/sh/tree.cc304
-rw-r--r--src/sh/user.cc445
-rw-r--r--src/sh/user.h92
-rw-r--r--src/test/EXPECTED.mt17
-rw-r--r--src/test/EXPECTED.ops1
-rw-r--r--src/test/cmd.hexp4
-rwxr-xr-xsrc/test/run.sh6
179 files changed, 22796 insertions, 0 deletions
diff --git a/src/LICENSE b/src/LICENSE
new file mode 100644
index 0000000..f6e636c
--- /dev/null
+++ b/src/LICENSE
@@ -0,0 +1,356 @@
1
2 This copyright does not cover server HTC code that use the system
3 by normal system calls - this is merely considered normal use of the
4 system, and does not fall under the heading of "derived work". Also
5 note that the GPL below is copyrighted by the Free Software
6 Foundation, but the instance of code that it refers to (the htcd
7 system) is copyrighted by me.
8
9 Also note that the only valid version of the GPL as far as the kernel
10 is concerned is _this_ particular version of the license (ie v2, not
11 v2.2 or v3.x or whatever), unless explicitly otherwise stated.
12
13 Henrik Rydberg (rydberg@euromail.se)
14
15----------------------------------------
16
17 GNU GENERAL PUBLIC LICENSE
18 Version 2, June 1991
19
20 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 Everyone is permitted to copy and distribute verbatim copies
23 of this license document, but changing it is not allowed.
24
25 Preamble
26
27 The licenses for most software are designed to take away your
28freedom to share and change it. By contrast, the GNU General Public
29License is intended to guarantee your freedom to share and change free
30software--to make sure the software is free for all its users. This
31General Public License applies to most of the Free Software
32Foundation's software and to any other program whose authors commit to
33using it. (Some other Free Software Foundation software is covered by
34the GNU Library General Public License instead.) You can apply it to
35your programs, too.
36
37 When we speak of free software, we are referring to freedom, not
38price. Our General Public Licenses are designed to make sure that you
39have the freedom to distribute copies of free software (and charge for
40this service if you wish), that you receive source code or can get it
41if you want it, that you can change the software or use pieces of it
42in new free programs; and that you know you can do these things.
43
44 To protect your rights, we need to make restrictions that forbid
45anyone to deny you these rights or to ask you to surrender the rights.
46These restrictions translate to certain responsibilities for you if you
47distribute copies of the software, or if you modify it.
48
49 For example, if you distribute copies of such a program, whether
50gratis or for a fee, you must give the recipients all the rights that
51you have. You must make sure that they, too, receive or can get the
52source code. And you must show them these terms so they know their
53rights.
54
55 We protect your rights with two steps: (1) copyright the software, and
56(2) offer you this license which gives you legal permission to copy,
57distribute and/or modify the software.
58
59 Also, for each author's protection and ours, we want to make certain
60that everyone understands that there is no warranty for this free
61software. If the software is modified by someone else and passed on, we
62want its recipients to know that what they have is not the original, so
63that any problems introduced by others will not reflect on the original
64authors' reputations.
65
66 Finally, any free program is threatened constantly by software
67patents. We wish to avoid the danger that redistributors of a free
68program will individually obtain patent licenses, in effect making the
69program proprietary. To prevent this, we have made it clear that any
70patent must be licensed for everyone's free use or not licensed at all.
71
72 The precise terms and conditions for copying, distribution and
73modification follow.
74
75 GNU GENERAL PUBLIC LICENSE
76 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
77
78 0. This License applies to any program or other work which contains
79a notice placed by the copyright holder saying it may be distributed
80under the terms of this General Public License. The "Program", below,
81refers to any such program or work, and a "work based on the Program"
82means either the Program or any derivative work under copyright law:
83that is to say, a work containing the Program or a portion of it,
84either verbatim or with modifications and/or translated into another
85language. (Hereinafter, translation is included without limitation in
86the term "modification".) Each licensee is addressed as "you".
87
88Activities other than copying, distribution and modification are not
89covered by this License; they are outside its scope. The act of
90running the Program is not restricted, and the output from the Program
91is covered only if its contents constitute a work based on the
92Program (independent of having been made by running the Program).
93Whether that is true depends on what the Program does.
94
95 1. You may copy and distribute verbatim copies of the Program's
96source code as you receive it, in any medium, provided that you
97conspicuously and appropriately publish on each copy an appropriate
98copyright notice and disclaimer of warranty; keep intact all the
99notices that refer to this License and to the absence of any warranty;
100and give any other recipients of the Program a copy of this License
101along with the Program.
102
103You may charge a fee for the physical act of transferring a copy, and
104you may at your option offer warranty protection in exchange for a fee.
105
106 2. You may modify your copy or copies of the Program or any portion
107of it, thus forming a work based on the Program, and copy and
108distribute such modifications or work under the terms of Section 1
109above, provided that you also meet all of these conditions:
110
111 a) You must cause the modified files to carry prominent notices
112 stating that you changed the files and the date of any change.
113
114 b) You must cause any work that you distribute or publish, that in
115 whole or in part contains or is derived from the Program or any
116 part thereof, to be licensed as a whole at no charge to all third
117 parties under the terms of this License.
118
119 c) If the modified program normally reads commands interactively
120 when run, you must cause it, when started running for such
121 interactive use in the most ordinary way, to print or display an
122 announcement including an appropriate copyright notice and a
123 notice that there is no warranty (or else, saying that you provide
124 a warranty) and that users may redistribute the program under
125 these conditions, and telling the user how to view a copy of this
126 License. (Exception: if the Program itself is interactive but
127 does not normally print such an announcement, your work based on
128 the Program is not required to print an announcement.)
129
130These requirements apply to the modified work as a whole. If
131identifiable sections of that work are not derived from the Program,
132and can be reasonably considered independent and separate works in
133themselves, then this License, and its terms, do not apply to those
134sections when you distribute them as separate works. But when you
135distribute the same sections as part of a whole which is a work based
136on the Program, the distribution of the whole must be on the terms of
137this License, whose permissions for other licensees extend to the
138entire whole, and thus to each and every part regardless of who wrote it.
139
140Thus, it is not the intent of this section to claim rights or contest
141your rights to work written entirely by you; rather, the intent is to
142exercise the right to control the distribution of derivative or
143collective works based on the Program.
144
145In addition, mere aggregation of another work not based on the Program
146with the Program (or with a work based on the Program) on a volume of
147a storage or distribution medium does not bring the other work under
148the scope of this License.
149
150 3. You may copy and distribute the Program (or a work based on it,
151under Section 2) in object code or executable form under the terms of
152Sections 1 and 2 above provided that you also do one of the following:
153
154 a) Accompany it with the complete corresponding machine-readable
155 source code, which must be distributed under the terms of Sections
156 1 and 2 above on a medium customarily used for software interchange; or,
157
158 b) Accompany it with a written offer, valid for at least three
159 years, to give any third party, for a charge no more than your
160 cost of physically performing source distribution, a complete
161 machine-readable copy of the corresponding source code, to be
162 distributed under the terms of Sections 1 and 2 above on a medium
163 customarily used for software interchange; or,
164
165 c) Accompany it with the information you received as to the offer
166 to distribute corresponding source code. (This alternative is
167 allowed only for noncommercial distribution and only if you
168 received the program in object code or executable form with such
169 an offer, in accord with Subsection b above.)
170
171The source code for a work means the preferred form of the work for
172making modifications to it. For an executable work, complete source
173code means all the source code for all modules it contains, plus any
174associated interface definition files, plus the scripts used to
175control compilation and installation of the executable. However, as a
176special exception, the source code distributed need not include
177anything that is normally distributed (in either source or binary
178form) with the major components (compiler, kernel, and so on) of the
179operating system on which the executable runs, unless that component
180itself accompanies the executable.
181
182If distribution of executable or object code is made by offering
183access to copy from a designated place, then offering equivalent
184access to copy the source code from the same place counts as
185distribution of the source code, even though third parties are not
186compelled to copy the source along with the object code.
187
188 4. You may not copy, modify, sublicense, or distribute the Program
189except as expressly provided under this License. Any attempt
190otherwise to copy, modify, sublicense or distribute the Program is
191void, and will automatically terminate your rights under this License.
192However, parties who have received copies, or rights, from you under
193this License will not have their licenses terminated so long as such
194parties remain in full compliance.
195
196 5. You are not required to accept this License, since you have not
197signed it. However, nothing else grants you permission to modify or
198distribute the Program or its derivative works. These actions are
199prohibited by law if you do not accept this License. Therefore, by
200modifying or distributing the Program (or any work based on the
201Program), you indicate your acceptance of this License to do so, and
202all its terms and conditions for copying, distributing or modifying
203the Program or works based on it.
204
205 6. Each time you redistribute the Program (or any work based on the
206Program), the recipient automatically receives a license from the
207original licensor to copy, distribute or modify the Program subject to
208these terms and conditions. You may not impose any further
209restrictions on the recipients' exercise of the rights granted herein.
210You are not responsible for enforcing compliance by third parties to
211this License.
212
213 7. If, as a consequence of a court judgment or allegation of patent
214infringement or for any other reason (not limited to patent issues),
215conditions are imposed on you (whether by court order, agreement or
216otherwise) that contradict the conditions of this License, they do not
217excuse you from the conditions of this License. If you cannot
218distribute so as to satisfy simultaneously your obligations under this
219License and any other pertinent obligations, then as a consequence you
220may not distribute the Program at all. For example, if a patent
221license would not permit royalty-free redistribution of the Program by
222all those who receive copies directly or indirectly through you, then
223the only way you could satisfy both it and this License would be to
224refrain entirely from distribution of the Program.
225
226If any portion of this section is held invalid or unenforceable under
227any particular circumstance, the balance of the section is intended to
228apply and the section as a whole is intended to apply in other
229circumstances.
230
231It is not the purpose of this section to induce you to infringe any
232patents or other property right claims or to contest validity of any
233such claims; this section has the sole purpose of protecting the
234integrity of the free software distribution system, which is
235implemented by public license practices. Many people have made
236generous contributions to the wide range of software distributed
237through that system in reliance on consistent application of that
238system; it is up to the author/donor to decide if he or she is willing
239to distribute software through any other system and a licensee cannot
240impose that choice.
241
242This section is intended to make thoroughly clear what is believed to
243be a consequence of the rest of this License.
244
245 8. If the distribution and/or use of the Program is restricted in
246certain countries either by patents or by copyrighted interfaces, the
247original copyright holder who places the Program under this License
248may add an explicit geographical distribution limitation excluding
249those countries, so that distribution is permitted only in or among
250countries not thus excluded. In such case, this License incorporates
251the limitation as if written in the body of this License.
252
253 9. The Free Software Foundation may publish revised and/or new versions
254of the General Public License from time to time. Such new versions will
255be similar in spirit to the present version, but may differ in detail to
256address new problems or concerns.
257
258Each version is given a distinguishing version number. If the Program
259specifies a version number of this License which applies to it and "any
260later version", you have the option of following the terms and conditions
261either of that version or of any later version published by the Free
262Software Foundation. If the Program does not specify a version number of
263this License, you may choose any version ever published by the Free Software
264Foundation.
265
266 10. If you wish to incorporate parts of the Program into other free
267programs whose distribution conditions are different, write to the author
268to ask for permission. For software which is copyrighted by the Free
269Software Foundation, write to the Free Software Foundation; we sometimes
270make exceptions for this. Our decision will be guided by the two goals
271of preserving the free status of all derivatives of our free software and
272of promoting the sharing and reuse of software generally.
273
274 NO WARRANTY
275
276 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
277FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
278OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
279PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
280OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
281MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
282TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
283PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
284REPAIR OR CORRECTION.
285
286 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
287WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
288REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
289INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
290OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
291TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
292YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
293PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
294POSSIBILITY OF SUCH DAMAGES.
295
296 END OF TERMS AND CONDITIONS
297
298 How to Apply These Terms to Your New Programs
299
300 If you develop a new program, and you want it to be of the greatest
301possible use to the public, the best way to achieve this is to make it
302free software which everyone can redistribute and change under these terms.
303
304 To do so, attach the following notices to the program. It is safest
305to attach them to the start of each source file to most effectively
306convey the exclusion of warranty; and each file should have at least
307the "copyright" line and a pointer to where the full notice is found.
308
309 <one line to give the program's name and a brief idea of what it does.>
310 Copyright (C) <year> <name of author>
311
312 This program is free software; you can redistribute it and/or modify
313 it under the terms of the GNU General Public License as published by
314 the Free Software Foundation; either version 2 of the License, or
315 (at your option) any later version.
316
317 This program is distributed in the hope that it will be useful,
318 but WITHOUT ANY WARRANTY; without even the implied warranty of
319 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
320 GNU General Public License for more details.
321
322 You should have received a copy of the GNU General Public License
323 along with this program; if not, write to the Free Software
324 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
325
326
327Also add information on how to contact you by electronic and paper mail.
328
329If the program is interactive, make it output a short notice like this
330when it starts in an interactive mode:
331
332 Gnomovision version 69, Copyright (C) year name of author
333 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
334 This is free software, and you are welcome to redistribute it
335 under certain conditions; type `show c' for details.
336
337The hypothetical commands `show w' and `show c' should show the appropriate
338parts of the General Public License. Of course, the commands you use may
339be called something other than `show w' and `show c'; they could even be
340mouse-clicks or menu items--whatever suits your program.
341
342You should also get your employer (if you work as a programmer) or your
343school, if any, to sign a "copyright disclaimer" for the program, if
344necessary. Here is a sample; alter the names:
345
346 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
347 `Gnomovision' (which makes passes at compilers) written by James Hacker.
348
349 <signature of Ty Coon>, 1 April 1989
350 Ty Coon, President of Vice
351
352This General Public License does not permit incorporating your program into
353proprietary programs. If your program is a subroutine library, you may
354consider it more useful to permit linking proprietary applications with the
355library. If this is what you want to do, use the GNU Library General
356Public License instead of this License.
diff --git a/src/hdb/README b/src/hdb/README
new file mode 100644
index 0000000..0db7269
--- /dev/null
+++ b/src/hdb/README
@@ -0,0 +1,154 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20HDB/1.2 FILE FORMAT SPECIFICATION Sat Feb 24 18:38:25 MET 2001
21
22MT AND MP SAFE
23
24One single format utilizing memory maps, and which is designed to
25work safely between processes and within a multi-threading process.
26To accomplish this, there are two types of locking mechanisms -
27one inter-process lock in the file header, and one MT lock implemented
28the usual way.
29
30The format is robust within each thread, except for changes in the
31table structure, which generates fatal error_t errors.
32
33The format includes a finite (32) number of tables, which should not
34be a real problem. Besides, a possible change is to move the frame
35pointer to a position inside, so that additional header could be
36added if needed.
37
38FILEFORMAT in HDB/1.2
39
40BYTES 1.2 NAME DESCRIPTION
4132 IDENT Identification header
424 LOCK Inter-process lock
434 MINOR Minor modification state number
444 MAJOR Major modification state number
454 FATAL Fatal modification state number
464 FILESIZE Size of file
474 FILETOP Size of used part
484 TABLES Number of table name strings
494 INDEX Which column is the order column.
5032 COMPNAME Comparison name
5132*32 TABLENAMES Table names
524 FRAME Start of record data
53* RECORDS Record list
54 4 mem amount of memory for this record
55 4 caps the capacity of this record - 0 means deleted
56 mem-8 data The data follows
570 ZEROS The rest of the file is padded with zeros.
58
59The records are always staying where they land; a minor change means
60a change in-place, a major change means a change leading to an index
61update, which could be a deletion, an insertion. Those are updated at
62will, and not seen until wanted. A fatal change is a change in the
63table structure, i.e., an insertion or deletion of a table. Also a
64table name change counts as fatal. The filesize used to be (earlier
65versions) a state needing attention as well, but not anymore.
66
67--
68
69HDB/1.11 FILE FORMAT SPECIFICATION Mon Jan 29 03:51:41 MET 2001
70
71STATIC/DYNAMIC mapping
72
73The header field determines whether the mapping is dynamic or static,
74i.e., static mapping creates a shared mmap and edits the records
75directly, whereas the dynamic mapping creates a private map and
76stores the changes on save only.
77
78The format changed quite a lot after all...
79
80FILEFORMAT in HDB/1.11
81
82BYTES 1.11 NAME DESCRIPTION
8332 IDENT Identification header
844 MODNUM Modification number
854 LOCK Soft lock
864 FILESIZE Size of file
874 FILETOP Size of used part
884 FIXED Whether fixed mapping or not
894 TABLES Number of table name strings
904 INDEX Which column is the order column.
9132 COMPNAME Comparison name
924 RECORDS Number of records in file.
93 tables
94 4,* name table name
95 4,* defaults default string
96 4 caps default sizes
97 [4],* records TABLES[RECORDS]
98
99Size info [4] always refers to the stringref-size, but the number of
100bytes actually written is as follows: for fixed maps, it is tabs[].caps,
101and for dynamic maps, it is capsize(), which is defined as (n=stringref-size)
102(4+n)&~3.
103
104--
105
106HDB/1.10 FILE FORMAT SPECIFICATION Thu Jan 25 00:42:49 MET 2001
107
108The HDB/1.0 format has been used widely in the software
109for our group (MST) during the last three years of so.
110The HDB/1.1 file format is binary compatible with 1.0,
111and merely consists of a formalization, along with a
112change in the internal manipulation scheme and a new
113hdb editor.
114
115FILE FORMAT IN 1.0 and 1.1
116
117BYTES 1.0/1.1 NAME DESCRIPTION
11832/variable HEAD Identification header.
119 Used to be exactly 32 bytes,
120 but see no point in that.
1214 TABLES Number of table name strings
122 4 dim bytes in string
123 * data string data
1244 DEFAULTS Number of default strings
125 4 dim bytes in string
126 * data string data
1274 ORDERBY Which column is the order column.
1284 dim Number of bytes in compname.
129* data string data
1304 RECORDS Number of records in file.
131 4 tables
132 4 dim
133 * data
1340/variable FOOTER File ends. Simple Footer.
135
136ADDITIONAL CHANGES BETWEEN 1.0 and 1.1
137
138The major difference - and the rationale for 1.1 - is
139the possiblity to edit files directly, as in mmap.
140To be able to do this, there is a need to force a minimum
141size to each field. This is done by padding the data
142with trailing zeros. This is ok since only string data
143is stored in the fields, and never binary data. Just think
144of it; if it was binary data, it would not be replaced
145by something the same size anyways, so thats forbidden
146in the direct-editing mode. It makes no difference to
147the normal operation.
148
149The default sizes for new fields are taken from the defaults
150table, which again is completely compatible. The only
151difference is that the zeros are stored as well, and hence
152cannot be defined just by the default string, but need an editor
153that specifies the sizes.
154
diff --git a/src/hdb/buffer.h b/src/hdb/buffer.h
new file mode 100644
index 0000000..9383753
--- /dev/null
+++ b/src/hdb/buffer.h
@@ -0,0 +1,38 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef BUFFERH
21#define BUFFERH
22
23#include <mt/mstring.h>
24#include <time.h>
25
26inline void LoadBuffer(mstring& buffer,const mstring& path)
27 throw(merror_t)
28{
29 if(buffer.load(path.c_str())<0) THROW("file: Could not load "<<path);
30}
31
32inline void SaveBuffer(const sref& buffer,const mstring& path,int prot=0600)
33 throw(merror_t)
34{
35 if(buffer.save(path,prot)<0) THROW("file: Could not save "<<path);
36}
37
38#endif
diff --git a/src/hdb/comp.cc b/src/hdb/comp.cc
new file mode 100644
index 0000000..3cb304a
--- /dev/null
+++ b/src/hdb/comp.cc
@@ -0,0 +1,78 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21using namespace std;
22
23const mstring compat="(compatibility)";
24const int zkey=0;
25
26OP2_IMPL(lti) {out<<(atoi(L)<atoi(R));}
27OP2_IMPL(lei) {out<<(atoi(L)<=atoi(R));}
28OP2_IMPL(gei) {out<<(atoi(L)>=atoi(R));}
29OP2_IMPL(gti) {out<<(atoi(L)>atoi(R));}
30
31void dbmap::setup()
32{
33 MLOCK(mutex);
34 if(M.empty()) {
35 opAddComp(M);
36 OP_ADDN(20,lti,lt.int,compat);
37 OP_ADDN(20,lei,le.int,compat);
38 OP_ADDN(20,gei,ge.int,compat);
39 OP_ADDN(20,gti,gt.int,compat);
40
41 M.add(new op_t("lt.case",20,M.get(sref("lt"))->f2,compat));
42 M.add(new op_t("gt.case",20,M.get(sref("gt"))->f2,compat));
43 M.add(new op_t("lt.nocase",20,M.get(sref("ltn"))->f2,compat));
44 M.add(new op_t("gt.nocase",20,M.get(sref("gtn"))->f2,compat));
45 }
46}
47
48const op_t* dbmap::CompOperator(const sref& s)
49{
50 if(M.empty()) setup();
51 const op_t* p=M.get(s);
52 if(!p) THROW("dbmap: could not find operator "<<s);
53 return p;
54}
55
56///////////////////////////////////////////////////////////////////
57
58void dbmap::Sort(const sref& tab,const sref& cmp) throw(merror_t)
59{
60 check();
61 int DO=0;
62 if(cmp.nempty()&&cmp!=compname) { compname=cmp; DO=1; }
63 if(tab.nempty()) { int col=Index(tab); if(col!=index) { index=col; DO=1; } }
64 if(DO) remap_recs();
65}
66
67void dbmap::Order(const sref& tab,const sref& cmp) throw(merror_t)
68{
69 check();
70 if(!wok) THROW("db: cannot order - readonly");
71 Sort(tab,cmp);
72 {
73 HEADLOCK(file);
74 file->head()->setcomp(index,compname);
75 remap_tabs();
76 }
77}
78
diff --git a/src/hdb/cvt.cc b/src/hdb/cvt.cc
new file mode 100644
index 0000000..4788bf1
--- /dev/null
+++ b/src/hdb/cvt.cc
@@ -0,0 +1,83 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21using namespace std;
22
23const mstring HEAD10="HTC DB File Format version 1.0\n";
24const mstring HEAD11="HDB/1.1";
25
26static fp_stream merr(stderr);
27
28static void Read(FILE* fp,mstring& s,int version) {
29 int n; fread(&n,4,1,fp);
30 switch(version) {
31 case 10:
32 s.resize(n);
33 fread(s.data(),1,n,fp);
34 break;
35 case 11:
36 s.resize(n-1);
37 fread(s.data(),1,n,fp);
38 s.resize(strlen(s.data()));
39 if(s.size()>=n) THROW("dbmap: assertion failed on dimension");
40 break;
41 default:
42 THROW("read: bad HDB version");
43 break;
44 }
45}
46
47void Convert(dbmap& db,const char* path)
48{
49 FILE* fp=fopen(path,"rb");
50 char line[1024];
51 fgets(line,1000,fp);
52 int version=0;
53 if(sref(line)==HEAD10) { fgetc(fp); version=10; }
54 else if(First(sref(line))==HEAD11) { version=11; }
55 if(version==0) THROW("hdbcvt: unknown HDB format");
56 int tables;
57 mstring s;
58 fread(&tables,4,1,fp);
59 for(int i=0;i<tables;i++) {
60 Read(fp,s,version);
61 db.InsertTable(i,s);
62 }
63 fread(&tables,4,1,fp);
64 if(tables!=db.Tables()) THROW("hdbcvt: bad table num\n");
65 spile defs(tables);
66 for(int i=0;i<tables;i++) Read(fp,defs[i],version);
67 merr<<"db: NOTE - default values no longer supported\n";
68 int index;
69 fread(&index,4,1,fp);
70 mstring compname;
71 Read(fp,compname,version);
72 db.Order(db.Table(index),compname);
73 int records;
74 fread(&records,4,1,fp);
75 for(int i=0;i<records;i++) {
76 int n; fread(&n,4,1,fp);
77 if(n!=tables) THROW("hdbcvt: bad table num\n");
78 spile rec(n);
79 for(int j=0;j<n;j++) Read(fp,rec[j],version);
80 int ok=db.Insert(rec,1);
81 if(ok<0) merr<<"hdbcvt: bad index ["<<rec[index]<<"] - not unique; skipped\n";
82 }
83}
diff --git a/src/hdb/db.cc b/src/hdb/db.cc
new file mode 100644
index 0000000..0cc9827
--- /dev/null
+++ b/src/hdb/db.cc
@@ -0,0 +1,276 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21#include <new>
22
23filemap* dbmap::flist;
24mutex_t dbmap::mutex;
25opmap dbmap::M;
26
27///////////////////////////////////////////////////////////////////////
28
29dbmap::dbmap():
30 wok(0),fatal(0),index(0),
31 compname(),file(0),tmap(),recs()
32{
33 minor=0;
34 major=0;
35}
36
37dbmap::~dbmap()
38{
39 Close();
40}
41
42///////////////////////////////////////////////////////////////////////
43
44void dbmap::remap_tabs()
45{
46 fatal=head()->fatal.get();
47 tmap.clear();
48 for(int i=0;i<Tables();i++) tmap.add(sref(head()->tabs[i]),i);
49}
50
51void dbmap::remap_recs()
52{
53 major=head()->major.get();
54 recs.clear();
55 int p=file->recs();
56 while(file->size(p)) {
57 record_t* rec=(record_t*)file->at(p);
58 if(rec->caps.get())
59 recs.push_back(idx_t(rec->at(index),rec));
60 p+=rec->mem.get();
61 }
62 recs.sort(CompOperator(compname));
63}
64
65int dbmap::remap()
66{
67 int state=0;
68 if(fatal!=head()->fatal.get()) { remap_tabs(); state|=4; }
69 if(major!=head()->major.get()) { remap_recs(); state|=2; }
70 if(minor!=head()->minor.get()) { minor=head()->minor.get(); state|=1; }
71 return state;
72}
73
74///////////////////////////////////////////////////////////////////////
75
76void Open(const mstring& path,int update=0,int prot=0600) throw(merror_t);
77void Saveas(const mstring& path,int prot=0600) throw(merror_t);
78void Close();
79
80void dbmap::Open(const mstring& path,int update,int prot) throw(merror_t)
81{
82 Close();
83 wok=update?1:0;
84 {
85 MLOCK(mutex);
86 for(filemap* p=flist;p;p=p->next)
87 if(p->Pathname()==path&&p->writable()==wok) { (file=p)->pushref(); break; }
88 if(!file) {
89 filemap* fm=new filemap(flist);
90 try { fm->open(path,wok,prot); fm->check(); file=flist=fm; }
91 catch(...) { delete fm; wok=0; throw; }
92 }
93 }
94 index=head()->index.get();
95 compname=head()->compname;
96 remap_tabs();
97 remap_recs();
98 minor=head()->minor.get();
99}
100
101void dbmap::Saveas(const mstring& path,int prot) throw(merror_t)
102{
103 file->save(path,prot);
104}
105
106void dbmap::Close()
107{
108 wok=0;
109 minor=0;
110 major=0;
111 fatal=0;
112 index=0;
113 compname.clear();
114 recs.clear();
115 tmap.clear();
116 if(file) {
117 MLOCK(mutex);
118 if(file->reference()) file->popref();
119 else {
120 if(flist==file) flist=file->next;
121 else for(filemap* p=flist;p;p=p->next)
122 if(p->next==file) { p->next=file->next; break; }
123 delete file;
124 }
125 file=0;
126 }
127}
128
129void dbmap::Sync()
130{
131 MLOCK(mutex);
132 for(filemap* p=flist;p;p=p->next) {
133 if(p->writable()) p->sync();
134 }
135}
136
137///////////////////////////////////////////////////////////////////////
138
139void dbmap::SetTable(int col,const sref& name) throw(merror_t)
140{
141 check();
142 if(!wok) THROW("db: cannot set table - readonly");
143 if(col<0||col>=Tables()) THROW("db: bad column");
144 HEADLOCK(file);
145 head()->set(col,name);
146 remap();
147}
148
149void dbmap::InsertTable(int col,const sref& name) throw(merror_t)
150{
151 check();
152 if(!wok) THROW("db: cannot insert table - readonly");
153 if(Tables()+1>file->maxtabs) THROW("db: too many tables");
154 if(col<0||col>Tables()) THROW("db: bad column");
155 {
156 HEADLOCK(file);
157 head()->insert(col,name);
158 int p=file->recs();
159 while(file->size(p)) {
160 record_t* rec=(record_t*)file->at(p);
161 if(rec->caps.get()) rec->insert(col);
162 p+=rec->mem.get();
163 }
164 head()->major.add(1);
165 }
166 index=head()->index.get();
167 compname=head()->compname;
168 remap();
169}
170
171void dbmap::RemTable(int col) throw(merror_t)
172{
173 check();
174 if(!wok) THROW("db: cannot remove table - readonly");
175 if(col<0||col>=Tables()) THROW("db: bad column");
176 if(col==head()->index.get()) THROW("db: cannot remove index table");
177 {
178 HEADLOCK(file);
179 head()->remove(col);
180 int p=file->recs();
181 while(file->size(p)) {
182 record_t* rec=(record_t*)file->at(p);
183 if(rec->caps.get()) rec->remove(col);
184 p+=rec->mem.get();
185 }
186 head()->major.add(1);
187 }
188 index=head()->index.get();
189 compname=head()->compname;
190 remap();
191}
192
193///////////////////////////////////////////////////////////////////////
194
195void dbmap::Get(int row,spile& list) throw(merror_t)
196{
197 check();
198 if(row<0||row>=recs.size()) THROW("db: not a valid record");
199 list.resize(Tables());
200 recs[row].rec->get(list);
201}
202
203void dbmap::Set(int row,int col,const sref& s) throw(merror_t)
204{
205 check();
206 if(!wok) THROW("db: cannot set - readonly");
207 if(row<0||row>=recs.size()) THROW("db: not a valid record");
208 if(col==index) THROW("db: cannot set index");
209 HEADLOCK(file);
210 record_t* rec=recs[row].rec;
211 int dim=rec->setreq(col,s);
212 if(dim>rec->caps.get()) {
213 rec=new(file->add(dim)) record_t(*rec);
214 file->rem(recs[row].rec);
215 recs[row].rec=rec;
216 head()->major.add(1);
217 major++;
218 }
219 rec->set(col,s);
220 head()->minor.add(1);
221 minor++;
222}
223
224void dbmap::Set(int row,const spile& list) throw(merror_t)
225{
226 check();
227 if(!wok) THROW("db: cannot set - readonly");
228 if(row<0||row>=recs.size()) THROW("db: not a valid record");
229 if(list.size()!=Tables())
230 THROW("db: wrong number of tables - "<<list.size()<<" should be "<<Tables());
231 HEADLOCK(file);
232 record_t* rec=recs[row].rec;
233 if(rec->at(index)!=list[index]) THROW("db: cannot set index");
234 int dim=record_t::req(list);
235 if(dim>rec->caps.get()) {
236 rec=new(file->add(dim)) record_t(*rec);
237 file->rem(recs[row].rec);
238 recs[row].rec=rec;
239 head()->major.add(1);
240 major++;
241 }
242 rec->set(list);
243 head()->minor.add(1);
244 minor++;
245}
246
247///////////////////////////////////////////////////////////////////////
248
249void dbmap::Rem(int row) throw(merror_t)
250{
251 if(!wok) THROW("db: cannot delete - readonly");
252 if(row<0||row>=recs.size()) THROW("db: not a valid record");
253 HEADLOCK(file);
254 file->rem(recs[row].rec);
255 recs.erase(recs.begin()+row);
256 head()->major.add(1);
257 major++;
258}
259
260int dbmap::Insert(const spile& list,int unique) throw(merror_t)
261{
262 check();
263 if(!wok) THROW("db: cannot insert - readonly");
264 if(index!=head()->index.get())
265 THROW("db: can only insert under normal order");
266 HEADLOCK(file);
267 remap();
268 int row=recs.get(list[index]);
269 if(row<0) {
270 record_t* rec=new(file->add(record_t::req(list))) record_t(list);
271 row=recs.add(rec->at(index),rec);
272 head()->major.add(1);
273 major++;
274 }
275 return row;
276}
diff --git a/src/hdb/db.h b/src/hdb/db.h
new file mode 100644
index 0000000..6621944
--- /dev/null
+++ b/src/hdb/db.h
@@ -0,0 +1,129 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef DBH
21#define DBH
22
23#include <hdb/sortable.h>
24#include <mt/msmap.h>
25
26////////////////////////////////////////////////////
27//
28// OK for MT and MP
29//
30
31class dbmap {
32public:
33 dbmap();
34 ~dbmap();
35
36 filemap::head_t* head() { return file->head(); }
37 const filemap::head_t* head() const { return file->head(); }
38
39 int remap();
40
41 int size() const { return recs.size(); }
42 int empty() const { return recs.empty(); }
43
44 const sref operator()(int row,int col) const throw(merror_t) {
45 check(); return recs[row].rec->at(col);
46 }
47 const sref at(int row,int col) const throw(merror_t) {
48 check(); return recs[row].rec->at(col);
49 }
50
51 ///////////////////////////////////////////////////////
52
53 void Get(int row,spile& list) throw(merror_t);
54 void Set(int row,int col,const sref& s) throw(merror_t);
55 void Set(int row,const spile& list) throw(merror_t);
56
57 ///////////////////////////////////////////////////////
58
59 void Rem(int row) throw(merror_t);
60 int Insert(const spile& list,int unique) throw(merror_t);
61
62 ///////////////////////////////////////////////////////
63
64 int Tables() const { return head()->tables.get(); }
65 const sref Table(int col) const { check(); return head()->get(col); }
66
67 ///////////////////////////////////////////////////////
68
69 void SetTable(int col,const sref& name) throw(merror_t);
70 void RemTable(int col) throw(merror_t);
71 void InsertTable(int col,const sref& name) throw(merror_t);
72
73 ///////////////////////////////////////////////////////
74
75 int Index() const { return index; }
76 int FindIndex(const sref& tab) const { return tmap.get(tab); }
77 int Index(const sref& tab) const throw(merror_t) {
78 int p=FindIndex(tab);
79 if(p<0) THROW("db: table ["<<tab<<"] does not exist");
80 return p;
81 }
82
83 ///////////////////////////////////////////////////////
84
85 const mstring& Compname() const { return compname; }
86
87 void Sort(const sref& tab,const sref& cmp) throw(merror_t);
88 void Order(const sref& tab,const sref& cmp) throw(merror_t);
89
90 int Find(const sref& key) const { return recs.get(key); }
91
92 ///////////////////////////////////////////////////////
93
94 void Open(const mstring& path,int update=0,int prot=0600) throw(merror_t);
95 void Saveas(const mstring& path,int prot=0600) throw(merror_t);
96 time_t Lastmod() const { return file->Lastmod(); }
97 void Close();
98
99 static void Sync();
100
101protected:
102 dbmap(const dbmap& db) {}
103 void operator=(const dbmap& db) {}
104
105 void check() const {
106 if(fatal!=head()->fatal.get()) THROW("db: fatal state change")
107 }
108
109 void remap_recs();
110 void remap_tabs();
111
112 static void setup();
113 static const op_t* CompOperator(const sref& s);
114
115 static filemap* flist;
116 static mutex_t mutex;
117 static opmap M;
118private:
119 int wok,minor,major,fatal,index;
120 mstring compname;
121 filemap* file;
122 rimap tmap;
123 indexmap recs;
124};
125
126void Convert(dbmap& db,const char* path);
127
128#endif
129
diff --git a/src/hdb/filemap.cc b/src/hdb/filemap.cc
new file mode 100644
index 0000000..b40644f
--- /dev/null
+++ b/src/hdb/filemap.cc
@@ -0,0 +1,302 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/filemap.h>
21#include <mt/split.h>
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <sys/mman.h>
25#include <new>
26using namespace std;
27
28const int PAGESIZE=getpagesize();
29const filemap::char32 HEADNAME="HDB/1.2\n";
30const filemap::char32 COMPNAME="lt";
31const mstring dev_tag="/dev/";
32
33const int TIMEOUT=20;
34
35///////////////////////////////////////////////////
36
37filemap::head_t::head_t()
38{
39 memcpy(ident,HEADNAME,sizeof(char32));
40 lock.set(0);
41 minor.set(0);
42 major.set(0);
43 fatal.set(0);
44 filesize.set(PAGESIZE);
45 filetop.set(sizeof(head_t));
46 tables.set(0);
47 index.set(0);
48 memcpy(compname,COMPNAME,sizeof(char32));
49 memset(tabs,0,maxtabs*sizeof(char32));
50 frame.set(sizeof(head_t));
51}
52
53filemap::head_t::head_t(const head_t* hd,int mem)
54{
55 memcpy(ident,HEADNAME,sizeof(char32));
56 lock.set(0);
57 minor.set(0);
58 major.set(0);
59 fatal.set(0);
60 filetop.set(sizeof(head_t)+mem);
61 filesize.set(PAGESIZE*int((filetop.get()+PAGESIZE)/PAGESIZE));
62 tables=hd->tables;
63 index=hd->index;
64 memcpy(compname,hd->compname,sizeof(char32));
65 memset(tabs,0,maxtabs*sizeof(char32));
66 for(int i=0;i<tables.get();i++)
67 memcpy(tabs[i],hd->tabs[i],sizeof(char32));
68 frame.set(sizeof(head_t));
69}
70
71void filemap::head_t::setcomp(int idx,const sref& s)
72{
73 index.set(idx);
74 s.copyto(compname,sizeof(char32));
75 fatal.add(1);
76}
77
78void filemap::head_t::set(int col,const sref& s)
79{
80 s.copyto(tabs[col],sizeof(char32));
81 fatal.add(1);
82}
83
84void filemap::head_t::insert(int col,const sref& s)
85{
86 for(int i=maxtabs-1;i>col;i--)
87 memcpy(tabs[i],tabs[i-1],sizeof(char32));
88 if(index.get()>=col&&index.get()<tables.get())
89 index.add(1);
90 s.copyto(tabs[col],sizeof(char32));
91 tables.add(1);
92 fatal.add(1);
93}
94
95void filemap::head_t::remove(int col)
96{
97 if(index.get()!=col) {
98 for(int i=col;i<maxtabs-1;i++)
99 memcpy(tabs[i],tabs[i+1],sizeof(char32));
100 if(index.get()>col) index.set(index.get()-1);
101 tables.add(-1);
102 fatal.add(1);
103 }
104}
105
106///////////////////////////////////////////////////////
107
108filemap::chunk_t::chunk_t(chunk_t* p,int fd,int wok,int off,int size)
109{
110 next=p;
111 end=(begin=off)+size;
112 map=(char*)mmap(0,size,PROT_READ|(wok?PROT_WRITE:0),MAP_SHARED,fd,off);
113 if(map==MAP_FAILED) { map=0; THROW("filemap: could not map chunk") }
114}
115
116filemap::chunk_t::~chunk_t()
117{
118 if(map) munmap(map,end-begin);
119}
120
121int filemap::chunk_t::fill(int off)
122{
123 if(own(off)) {
124 at(off)->mem.set(end-off);
125 at(off)->caps.set(0);
126 return end;
127 }
128 else return off;
129}
130
131void filemap::chunk_t::sync()
132{
133 msync(map,end-begin,MS_SYNC);
134}
135
136///////////////////////////////////////////////////////
137
138void filemap::remap()
139{
140 while(mem->end<hd->filesize.get()) {
141 mem=new chunk_t(mem,fd,wok,mem->end,mem->size()<<1);
142 }
143}
144
145filemap::rec_t* filemap::add(int n)
146{
147 int caps=sizeof(rec_t),dim=caps+n;
148 while(caps<dim) caps<<=1;
149 remap();
150 if(hd->filesize.get()<mem->end) {
151 ftruncate(fd,mem->end);
152 hd->filesize.set(mem->end);
153 }
154 while(hd->filetop.get()+caps>mem->end) {
155 hd->filetop.set(mem->fill(hd->filetop.get()));
156 mem=new chunk_t(mem,fd,wok,mem->end,mem->size()<<1);
157 ftruncate(fd,mem->end);
158 hd->filesize.set(mem->end);
159 }
160 rec_t* rec=at(hd->filetop.get());
161 hd->filetop.add(caps);
162 rec->mem.set(caps);
163 rec->caps.set(n);
164 return rec;
165}
166
167void filemap::rem(rec_t* rec)
168{
169 rec->caps.set(0);
170}
171
172///////////////////////////////////////////////////////
173
174filemap::filemap(filemap* p):
175 next(p),fd(-1),wok(0),refs(0),pathname(),hd(0),mem(0),nodelock(0)
176{
177 memset(&mutex,0,sizeof(mutex_t));
178}
179
180filemap::filemap(filemap* p,const mstring& path,int update,int prot):
181 next(p),fd(-1),wok(0),refs(0),pathname(),hd(0),mem(0),nodelock(0)
182{
183 memset(&mutex,0,sizeof(mutex_t));
184 open(path,update,prot);
185}
186
187filemap::~filemap()
188{
189 close();
190}
191
192///////////////////////////////////////////////////////
193
194void filemap::open(const mstring& path,int update,int prot) throw(merror_t)
195{
196 close();
197 if(update) {
198 if(path.left(5)!=dev_tag) nodelock=new nodelock_t(path);
199 else nodelock=0;
200 wok=1;
201 }
202 else {
203 nodelock=0;
204 wok=0;
205 }
206 fd=::open(path.c_str(),wok?O_RDWR|O_CREAT:O_RDONLY,prot);
207 if(fd<0) THROW("filemap: could not open "<<path);
208 int fsize=lseek(fd,0,SEEK_END);
209 int mapsize=PAGESIZE*int((fsize+PAGESIZE)/PAGESIZE);
210 hd=(head_t*)(mem=new chunk_t(0,fd,wok,0,mapsize))->map;
211 if(fsize<sizeof(head_t)) {
212 if(wok) { ftruncate(fd,fsize=mapsize); new(hd) head_t(); }
213 else THROW("filemap: not a HDB file");
214 }
215 if(First(sref(hd->ident))!=First(sref(HEADNAME))) THROW("filemap: bad version");
216 remap();
217 if(fsize!=hd->filesize.get())
218 THROW("filemap: "<<path<<" has bad filesize - run hdbfix");
219 pathname=path;
220}
221
222void filemap::check() throw(merror_t)
223{
224 // Make a consistency test, but NEVER change filetop!!!
225 // Severe loss of data may occur if you do
226 // Use hdbfix in case the db seems corrupted
227 int p=recs(),ft=hd->filetop.get();
228 while(size(p)) {
229 rec_t* rec=at(p);
230 p+=rec->mem.get();
231 }
232 if(p<ft) THROW("filemap: "<<pathname<<" is corrupted - run hdbfix");
233 // OK, at least no data is missing. Usually p==ft,
234 // but since no locking is done here, another process
235 // may make changes that turn p>ft.
236}
237
238void filemap::save(const mstring& path,int prot) throw(merror_t)
239{
240 if(path==pathname) THROW("filemap: cannot overwrite current file");
241 int mfd=::open(path.c_str(),O_RDWR|O_CREAT|O_TRUNC,prot);
242 if(mfd<0) THROW("filemap: could not open "<<path<<" for writing");
243 int caps=0,p=recs();
244 while(size(p)) {
245 rec_t* rec=at(p);
246 if(rec->caps.get()) caps+=rec->mem.get();
247 p+=rec->mem.get();
248 }
249 head_t mhd(hd,caps);
250 ::write(mfd,&mhd,sizeof(head_t));
251 p=recs();
252 while(size(p)) {
253 rec_t* rec=at(p);
254 if(rec->caps.get()) ::write(mfd,rec,rec->mem.get());
255 p+=rec->mem.get();
256 }
257 ftruncate(mfd,mhd.filesize.get());
258 ::close(mfd);
259}
260
261void filemap::close()
262{
263 while(mem) { chunk_t* p=mem->next; delete mem; mem=p; }
264 hd=0;
265 wok=0;
266 refs=0;
267 if(fd>=0) { ::close(fd); fd=-1; }
268 delete nodelock; nodelock=0;
269 pathname.clear();
270}
271
272void filemap::sync()
273{
274 for(chunk_t* p=mem;p;p=p->next) p->sync();
275}
276
277///////////////////////////////////////////////////////
278
279void filemap::lock()
280{
281 if(hd) {
282 MLOCK(mutex);
283 if((volatile long&)hd->lock) {
284 time_t end=time(0)+TIMEOUT;
285 while((volatile long&)hd->lock&&time(0)<end);
286 }
287 hd->lock.set(1);
288 }
289}
290
291void filemap::unlock()
292{
293 if(hd) hd->lock.set(0);
294}
295
296///////////////////////////////////////////////////////
297
298time_t filemap::Lastmod() const
299{
300 struct stat fs; fstat(fd,&fs); return fs.st_mtime;
301}
302
diff --git a/src/hdb/filemap.h b/src/hdb/filemap.h
new file mode 100644
index 0000000..d6af7eb
--- /dev/null
+++ b/src/hdb/filemap.h
@@ -0,0 +1,196 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef FILEMAPH
21#define FILEMAPH
22
23#include <mt/mstring.h>
24#include <mt/lock.h>
25#include <mt/mlock.h>
26#include <mt/mlock.h>
27#include <netinet/in.h>
28
29//////////////////////////////////////////////
30//
31// NOTE that filemap is MT unsafe:
32// it needs to be called from dbmap
33//
34// The exception is when filelocking;
35// that's MT safe per filemap, and hence
36// should not be locked further
37//
38
39#define HEADLOCK(fm) headlock_t headlock(fm)
40
41//////////////////////////////////////////////////////
42
43// network byteorder
44class byte4 {
45public:
46 byte4() {} // must be uninitialized
47 explicit byte4(int h): n(htonl(h)) {}
48 void set(int h) { n=htonl(h); }
49 void add(int h) { n=htonl(ntohl(n)+h); }
50 int get() const { return ntohl(n); }
51private:
52 long n;
53};
54
55//////////////////////////////////////////////////////
56
57class filemap {
58public:
59 typedef char char32[32];
60 static const int maxtabs=32;
61
62 ////////////////////////////////////////////////////
63
64 struct head_t {
65 char32 ident;
66 byte4 lock;
67 byte4 minor;
68 byte4 major;
69 byte4 fatal;
70 byte4 filesize;
71 byte4 filetop;
72 byte4 tables;
73 byte4 index;
74 char32 compname;
75 char32 tabs[maxtabs];
76 byte4 frame;
77
78 head_t();
79 head_t(const head_t* hd,int mem);
80
81 void setcomp(int idx, const sref& cp);
82
83 sref get(int col) const { return sref(tabs[col]); }
84 void set(int col,const sref& s);
85 void insert(int col,const sref& s);
86 void remove(int col);
87 };
88
89 head_t* head() { return hd; }
90 const head_t* head() const { return hd; }
91
92 ///////////////////////////////////////////////////////
93
94 struct rec_t {
95 byte4 mem;
96 byte4 caps;
97 };
98
99 rec_t* at(int off) {
100 for(chunk_t* p=mem;p;p=p->next) if(p->own(off)) return p->at(off); return 0;
101 }
102 const rec_t* at(int off) const {
103 for(const chunk_t* p=mem;p;p=p->next) if(p->own(off)) return p->at(off);
104 return 0;
105 }
106
107 int recs() const { return hd->frame.get(); }
108 int size(int off) const {
109 if(off<hd->filetop.get()) {
110 for(const chunk_t* p=mem;p;p=p->next)
111 if(p->own(off)) return p->at(off)->mem.get();
112 }
113 return 0;
114 }
115
116 ///////////////////////////////////////////////////////
117
118 void remap();
119
120 rec_t* add(int n);
121 void rem(rec_t* rec);
122
123 ///////////////////////////////////////////////////////
124
125 filemap(filemap* p);
126 filemap(filemap* p,const mstring& path,int update=0,int prot=0600);
127 ~filemap();
128
129 filemap* next;
130
131 ///////////////////////////////////////////////////////
132
133 void open(const mstring& path,int update=0,int prot=0600) throw(merror_t);
134 void save(const mstring& path,int prot=0600) throw(merror_t);
135 void check() throw(merror_t);
136 void close();
137 void sync();
138
139 const mstring& Pathname() const { return pathname; }
140 time_t Lastmod() const;
141
142 int reference() const { return refs; }
143 int writable() const { return wok; }
144
145 void pushref() { refs++; }
146 void popref() { refs--; }
147
148 ///////////////////////////////////////////////////////
149
150 void lock();
151 void unlock();
152
153 ///////////////////////////////////////////////////////
154
155protected:
156 struct chunk_t {
157 chunk_t* next;
158 long begin;
159 long end;
160 char* map;
161
162 int size() const { return end-begin; }
163
164 chunk_t(chunk_t* p,int fd,int wok,int off,int size);
165 ~chunk_t();
166
167 int own(int off) const { return off>=begin&&off<end; }
168 void sync();
169
170 rec_t* at(int off) { return (rec_t*)(map+(off-begin)); }
171 const rec_t* at(int off) const { return (rec_t*)(map+(off-begin)); }
172
173 int fill(int off);
174 };
175private:
176 int fd,wok,refs;
177 mstring pathname;
178 head_t* hd;
179 chunk_t* mem;
180 mutex_t mutex;
181 nodelock_t* nodelock;
182private:
183 filemap(const filemap&) {}
184 void operator=(const filemap&) {}
185};
186
187//////////////////////////////////////////////////////
188
189struct headlock_t {
190 filemap* fm;
191 headlock_t(filemap* f) : fm(f) { fm->lock(); }
192 ~headlock_t() { if(fm) fm->unlock(); }
193};
194
195#endif
196
diff --git a/src/hdb/hdbcvt.cc b/src/hdb/hdbcvt.cc
new file mode 100644
index 0000000..ece70f0
--- /dev/null
+++ b/src/hdb/hdbcvt.cc
@@ -0,0 +1,50 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21#include <mt/lock.h>
22
23static fp_stream mout(stdout),merr(stderr);
24
25main(int argc,char* argv[]) throw(merror_t) try
26{
27 if(argc<2) {
28 merr<<"Usage: "<<argv[0]<<" <db> [<index> <cp>]\n";
29 return -1;
30 }
31 mstring newfile=argv[1];
32 mstring oldfile=newfile+sref(".bak");
33 rename(newfile.c_str(),oldfile.c_str());
34 dbmap db;
35 try {
36 db.Open(oldfile);
37 if(argc>3) db.Sort(sref(argv[2]),sref(argv[3]));
38 db.Saveas(newfile);
39 }
40 catch(const merror_t& e) {
41 merr<<"Opened as newfile, old version\n";
42 db.Open(newfile,1);
43 Convert(db,oldfile.c_str());
44 }
45 return 0;
46}
47catch(const merror_t& e) {
48 merr<<e.desc<<"\n";
49 return -1;
50}
diff --git a/src/hdb/hdbfix.cc b/src/hdb/hdbfix.cc
new file mode 100644
index 0000000..b82f151
--- /dev/null
+++ b/src/hdb/hdbfix.cc
@@ -0,0 +1,140 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21
22static fp_stream mout(stdout),merr(stderr);
23
24main(int argc,char* argv[]) try
25{
26 if(argc<2) {
27 mout<<"Usage: "<<argv[0]<<" [-s] <path>\n";
28 return -1;
29 }
30 mstring path; int silent;
31 if(argc>2) { silent=1; path=argv[2]; }
32 else { silent=0; path=argv[1]; }
33 mstring map; if(map.load(path)<0) THROW("hdbfix: could not open "<<path);
34 filemap::head_t head;
35 mstring version=First(sref(head.ident,sizeof(head.ident)));
36 memcpy(&head,map.data(),sizeof(head));
37 mstring cver=First(sref(head.ident,sizeof(head.ident)));
38 mstring answer;
39 int save=0;
40 if(version!=cver) {
41 merr<<path<<": Not a "<<version<<" file\n";
42 return -1;
43 }
44 else {
45 int top=head.frame.get(),last=0;
46 while(top<head.filetop.get()&&top<map.size()) {
47 filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top);
48 if(rec->mem.get()<=0) {
49 if(!silent&&rec->mem.get()<0)
50 mout<<"ending mem: "<<rec->mem.get()<<"\n";
51 break;
52 }
53 last=top;
54 top+=rec->mem.get();
55 }
56 if(top==head.filetop.get()&&head.filesize.get()==map.size()) {
57 if(!silent) mout<<path<<": OK\n";
58 }
59 else {
60 mout<<path<<": CORRUPTED\n";
61 if(silent) return 0;
62 mout<<"\n";
63 mout<<"Head info:\n";
64 mout<<"Size: "<<head.filesize.get()<<"\n";
65 mout<<"Frame: "<<head.frame.get()<<"\n";
66 mout<<"Top: "<<head.filetop.get()<<"\n";
67 mout<<"\n";
68
69 mout<<"Actual sizes:\n";
70 mout<<"Size: "<<map.size()<<"\n";
71 mout<<"Last: "<<last<<"\n";
72 mout<<"End: "<<top<<"\n";
73 mout<<"\n";
74
75 if(map.size()!=head.filesize.get()) {
76 mout<<"Filesizes differ - do you want to set the filesize to "
77 <<head.filesize.get()<<"?\n";
78 getline(answer,stdin); answer.tolower();
79 if(*answer=='y') {
80 map.resize(head.filesize.get());
81 save=1;
82 mout<<"Done.\n";
83 }
84 else {
85 mout<<"No change - quitting.\n";
86 return 0;
87 }
88 }
89
90 int nend=0,end=head.filetop.get();
91 for(int p=head.filetop.get()-4;p>=last;p-=4){
92 int val=ntohl(*(long*)(map.data()+p));
93 if(p+val==end) { nend++; end=p; }
94 }
95 int gap=end-top;
96
97 mout<<"GAP DATA\n";
98 mout<<"==============================\n";
99 for(int i=top;i<end;i++) {
100 if(cset_printable.test(map[i])) mout.put(map[i]);
101 else mout<<"["<<(int)map[i]<<"]";
102 }
103 mout<<"\n==============================\n";
104 mout<<"\n";
105
106 mout<<"At-end sequence:\n";
107 mout<<"Start: "<<end<<"\n";
108 mout<<"Gap: "<<gap<<"\n";
109 mout<<"\n";
110
111 if(gap>0) {
112 mout<<"Do you want to mark the gap as deleted?\n";
113 getline(answer,stdin); answer.tolower();
114 if(*answer=='y') {
115 filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top);
116 rec->mem.set(gap);
117 rec->caps.set(0);
118 save=1;
119 mout<<"Done.\n";
120 }
121 else {
122 mout<<"No change - quitting.\n";
123 return 0;
124 }
125 }
126 }
127 }
128
129 if(save) map.save(path);
130
131 return 0;
132}
133catch(const merror_t& e) {
134 merr<<e.desc<<"\n";
135 return -1;
136}
137catch(...) {
138 merr<<"FATAL ERROR\n";
139 return -1;
140}
diff --git a/src/hdb/hdbtest.cc b/src/hdb/hdbtest.cc
new file mode 100644
index 0000000..89169da
--- /dev/null
+++ b/src/hdb/hdbtest.cc
@@ -0,0 +1,153 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21
22static fp_stream mout(stdout),merr(stderr);
23
24main(int argc,char* argv[]) try
25{
26 if(argc<2) {
27 mout<<"Usage: "<<argv[0]<<" [-s] <path>\n";
28 return -1;
29 }
30 mstring path; int silent;
31 if(argc>2) { silent=atoi(argv[1]); path=argv[2]; }
32 else { silent=0; path=argv[1]; }
33 mstring map; if(map.load(path)<0) THROW("hdbfix: could not open "<<path);
34 filemap::head_t head;
35 mstring version=First(sref(head.ident,sizeof(head.ident)));
36 memcpy(&head,map.data(),sizeof(head));
37 mstring cver=First(sref(head.ident,sizeof(head.ident)));
38 mstring answer;
39 int save=0;
40 if(version!=cver) {
41 merr<<path<<": Not a "<<version<<" file\n";
42 return -1;
43 }
44 else {
45 int top=head.frame.get(),last=0;
46 while(top<head.filetop.get()&&top<map.size()) {
47 filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top);
48 if(rec->mem.get()<=0) break;
49 if(silent) {
50 if(silent==top) {
51 mout<<top<<" *************\n";
52 for(int i=0;i<65536;i++) {
53 char c=map.data()[top+i];
54 if(cset_printable.test(c)) mout.put(c);
55 }
56 mout<<"\n\n";
57 }
58 }
59 else {
60 mout<<top<<" *************\n";
61 for(int i=0;i<1024;i++) {
62 char c=map.data()[top+i];
63 if(cset_printable.test(c)) mout.put(c);
64 }
65 mout<<"\n\n";
66 }
67 last=top; top+=rec->mem.get();
68 }
69 if(top==head.filetop.get()&&head.filesize.get()==map.size()) {
70 if(!silent) mout<<path<<": OK\n";
71 }
72 else {
73 mout<<path<<": CORRUPTED\n";
74 if(silent) return 0;
75 mout<<"\n";
76 mout<<"Head info:\n";
77 mout<<"Size: "<<head.filesize.get()<<"\n";
78 mout<<"Frame: "<<head.frame.get()<<"\n";
79 mout<<"Top: "<<head.filetop.get()<<"\n";
80 mout<<"\n";
81
82 mout<<"Actual sizes:\n";
83 mout<<"Size: "<<map.size()<<"\n";
84 mout<<"Last: "<<last<<"\n";
85 mout<<"End: "<<top<<"\n";
86 mout<<"\n";
87
88 if(map.size()!=head.filesize.get()) {
89 mout<<"Filesizes differ - do you want to set the filesize to "
90 <<head.filesize.get()<<"?\n";
91 getline(answer,stdin); answer.tolower();
92 if(*answer=='y') {
93 map.resize(head.filesize.get());
94 save=1;
95 mout<<"Done.\n";
96 }
97 else {
98 mout<<"No change - quitting.\n";
99 return 0;
100 }
101 }
102
103 int nend=0,end=head.filetop.get();
104 for(int p=head.filetop.get()-4;p>=last;p-=4){
105 unsigned val=*(unsigned*)(map.data()+p);
106 if(p+val==end) { nend++; end=p; }
107 }
108 int gap=end-top;
109
110 mout<<"GAP DATA\n";
111 mout<<"==============================\n";
112 for(int i=top;i<end;i++) {
113 if(cset_printable.test(map[i])) mout.put(map[i]);
114 else if(map[i]) mout<<"["<<(int)map[i]<<"]";
115 }
116 mout<<"\n==============================\n";
117 mout<<"\n";
118
119 mout<<"At-end sequence:\n";
120 mout<<"Start: "<<end<<"\n";
121 mout<<"Gap: "<<gap<<"\n";
122 mout<<"\n";
123
124 if(gap>0) {
125 mout<<"Do you want to mark the gap as deleted?\n";
126 getline(answer,stdin); answer.tolower();
127 if(*answer=='y') {
128 filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top);
129 rec->mem.set(gap);
130 rec->caps.set(0);
131 save=1;
132 mout<<"Done.\n";
133 }
134 else {
135 mout<<"No change - quitting.\n";
136 return 0;
137 }
138 }
139 }
140 }
141
142 if(save) map.save(path);
143
144 return 0;
145}
146catch(const merror_t& e) {
147 merr<<e.desc<<"\n";
148 return -1;
149}
150catch(...) {
151 merr<<"FATAL ERROR\n";
152 return -1;
153}
diff --git a/src/hdb/sortable.cc b/src/hdb/sortable.cc
new file mode 100644
index 0000000..39adf58
--- /dev/null
+++ b/src/hdb/sortable.cc
@@ -0,0 +1,81 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/sortable.h>
21#include <algorithm>
22using namespace std;
23
24int int_stream::appc(char c) { return val=c,1; }
25int int_stream::appi(int i) { return val=i,1; }
26int int_stream::appf(double f) { return val=(int)f,1; }
27int int_stream::apps(const sref& s) { return val=atoi(s),s.size(); }
28
29///////////////////////////////////////////////////
30
31record_t::record_t(const spile& list)
32{
33 pos[0].set(0);
34 for(int i=0;i<list.size();i++) {
35 memcpy(data+pos[i].get(),list[i].data(),list[i].size());
36 pos[i+1].set(pos[i].get()+list[i].size());
37 }
38 for(int i=list.size();i<maxtabs;i++) pos[i+1]=pos[i];
39}
40
41void record_t::set(const spile& list)
42{
43 pos[0].set(0);
44 for(int i=0;i<list.size();i++) {
45 memcpy(data+pos[i].get(),list[i].data(),list[i].size());
46 pos[i+1].set(pos[i].get()+list[i].size());
47 }
48 for(int i=list.size();i<maxtabs;i++) pos[i+1]=pos[i];
49}
50
51void record_t::resize(int col,int n)
52{
53 int delta=n+pos[col].get()-pos[col+1].get();
54 if(delta) {
55 memmove(data+pos[col+1].get()+delta,data+pos[col+1].get(),
56 pos[maxtabs].get()-pos[col+1].get());
57 for(int i=col+1;i<=maxtabs;i++) pos[i].add(delta);
58 }
59}
60
61///////////////////////////////////////////////////
62
63int indexmap::get(const sref& t) const
64{
65 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),idx_t(t,0),comp);
66 return p.first!=p.second?p.first-begin():-1;
67}
68
69int indexmap::add(const sref& t,record_t* rec)
70{
71 idx_t tmp(t,rec);
72 pair<iterator,iterator> p=equal_range(begin(),end(),tmp,comp);
73 if(p.first!=p.second) return &(*p.first=tmp)-begin();
74 else return insert(p.second,tmp)-begin();
75}
76
77void indexmap::sort(const op_t* op)
78{
79 comp.func=op->f2;
80 ::sort(begin(),end(),comp);
81}
diff --git a/src/hdb/sortable.h b/src/hdb/sortable.h
new file mode 100644
index 0000000..7de0aa8
--- /dev/null
+++ b/src/hdb/sortable.h
@@ -0,0 +1,138 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef SORTABLEH
21#define SORTABLEH
22
23#include <hdb/filemap.h>
24#include <ops/express.h>
25#include <mt/mset.h>
26
27////////////////////////////////////////////////////
28//
29// NOTE that these classes are not MT safe:
30// need to be called from dbamp
31//
32
33struct record_t : public filemap::rec_t {
34 static const int maxtabs=filemap::maxtabs;
35 static const int recsize=(maxtabs+1)*sizeof(long);
36
37 byte4 pos[maxtabs+1];
38 char data[sizeof(byte4)];
39
40 int size() const { return pos[maxtabs].get()-pos[0].get(); }
41 int size(int i) const { return pos[i+1].get()-pos[i].get(); }
42
43 sref at(int i) const { return sref(data+pos[i].get(),size(i)); }
44
45 /////////////////////////////////////////////////
46
47 record_t(const record_t& rec) {
48 for(int i=0;i<=maxtabs;i++) pos[i]=rec.pos[i];
49 memcpy(data,rec.data,rec.caps.get());
50 }
51 record_t(const spile& list);
52
53 /////////////////////////////////////////////////
54
55 void get(spile& list) const {
56 for(int i=0;i<list.size();i++) list[i]=at(i);
57 }
58
59 /////////////////////////////////////////////////
60
61 int setreq(int col,const sref& s) const {
62 return recsize+size()+s.size()-size(col);
63 }
64 inline static int req(const spile& list) {
65 int n=0; for(int i=0;i<list.size();i++) n+=list[i].size();
66 return recsize+n;
67 }
68
69 /////////////////////////////////////////////////
70
71 void set(int col,const sref& s) {
72 resize(col,s.size());
73 memcpy(data+pos[col].get(),s.data(),s.size());
74 }
75
76 void set(const spile& list);
77
78 /////////////////////////////////////////////////
79
80 void insert(int col) {
81 for(int i=maxtabs;i>col;i--) pos[i]=pos[i-1];
82 }
83 void remove(int col) {
84 resize(col,0);
85 for(int i=col;i<maxtabs;i++) pos[i]=pos[i+1];
86 }
87
88 /////////////////////////////////////////////////
89
90 void resize(int col,int n);
91
92};
93
94////////////////////////////////////////////////////////////////////
95
96struct int_stream : public mstream {
97 int val;
98
99 int_stream() : val(0) {}
100
101 int appc(char c);
102 int appi(int i);
103 int appf(double f);
104 int apps(const sref& s);
105};
106
107////////////////////////////////////////////////////////////////////
108
109struct idx_t {
110 sref key; record_t* rec;
111 idx_t(const sref& t,record_t* p) : key(t),rec(p) {}
112};
113
114class indexmap : public mrvec<idx_t> {
115public:
116 typedef mrvec<idx_t>::iterator iterator;
117 typedef mrvec<idx_t>::const_iterator const_iterator;
118
119 struct comp_t {
120 op_t::op2_t func;
121 comp_t() : func(0) {}
122 comp_t(const op_t* op) : func(op->f2) {}
123 bool operator()(const idx_t& a,const idx_t& b) const {
124 int_stream res;
125 op_env env;
126 func(res,env,a.key,b.key);
127 return res.val;
128 }
129 };
130
131 int get(const sref& t) const;
132 int add(const sref& t,record_t* rec);
133 void sort(const op_t* op);
134private:
135 comp_t comp;
136};
137
138#endif
diff --git a/src/hdb/test.cc b/src/hdb/test.cc
new file mode 100644
index 0000000..b8d335b
--- /dev/null
+++ b/src/hdb/test.cc
@@ -0,0 +1,52 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21
22static fp_stream merr(stderr);
23
24main(int argc,char* argv[]) throw(merror_t) try
25{
26 if(argc<2) {
27 merr<<"Usage: "<<argv[0]<<" <path>\n";
28 return -1;
29 }
30 dbmap m;
31 m.Open(argv[1]);
32
33 merr<<m.head()->filesize.get()<<"\n";
34 merr<<m.head()->filetop.get()<<"\n";
35 merr<<m.head()->frame.get()<<"\n";
36
37 for(int j=0;j<m.Tables();j++) merr<<m.Table(j)<<" ";
38 merr<<"\n\n";
39
40 for(int i=0;i<m.size();i++) {
41 //for(int j=0;j<m.Tables();j++) merr<<m(i,j)<<" ";
42 for(int j=0;j<1;j++) merr<<m(i,j)<<" ";
43
44 merr<<"\n";
45 }
46
47 return 0;
48}
49catch(const merror_t& e) {
50 merr<<e.desc<<"\n";
51 return -1;
52}
diff --git a/src/hed/edit.cc b/src/hed/edit.cc
new file mode 100644
index 0000000..b38b1e9
--- /dev/null
+++ b/src/hed/edit.cc
@@ -0,0 +1,262 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hed/edit.h>
21#include <hed/input.h>
22#include <string.h>
23#include <malloc.h>
24
25const mstring end_tag="~";
26
27Editor::Line::Line()
28{
29 line=(char*)malloc(MAXCOLS);
30 line[0]=0;
31 dim=1;
32}
33Editor::Line::Line(char* p,int s)
34{
35 line=(char*)malloc(MAXCOLS);
36 memcpy(line,p,s);
37 dim=s;
38}
39Editor::Line::~Line()
40{
41 delete line;
42}
43int Editor::Line::Insert(int pos,char c)
44{
45 if(pos>=dim) pos=dim-1;
46 if(dim<MAXCOLS) {
47 memmove(line+pos+1,line+pos,dim-pos);
48 line[pos]=c;
49 dim++;
50 return 1;
51 }
52 else return 0;
53}
54int Editor::Line::Append(const Line* p)
55{
56 if(dim-1+p->dim<=MAXCOLS) {
57 memcpy(line+dim-1,p->line,p->dim);
58 dim+=p->dim-1;
59 return 1;
60 }
61 else return 0;
62}
63Editor::Line* Editor::Line::Break(int pos)
64{
65 if(pos>=dim) pos=dim-1;
66 Line* p=new Line(line+pos,dim-pos);
67 line[pos]=0;
68 dim=pos+1;
69 return p;
70}
71void Editor::Line::Delete(int pos)
72{
73 if(dim-1>pos) {
74 memmove(line+pos,line+pos+1,dim-pos-1);
75 dim--;
76 }
77}
78
79/////////////////////////////////////////////////////////////////////////
80
81Editor::Editor(const mstring& s,int ex) :
82 path(s),
83 from(0),lines(Lines()),atline(0),size(0),
84 tab(0),cols(Columns()),atcol(0),exclusive(ex)
85{
86 memset(map,0,sizeof(Line*)*MAXLINES);
87 map[0]=new Line();
88 size=1;
89 caption=path;
90 caption+=sref(" ok (ESC to go back)");
91 if(!exclusive) caption+=sref(" (readonly)");
92}
93Editor::~Editor()
94{
95 for(int i=0;i<size;i++) delete map[i];
96}
97
98void Editor::Show()
99{
100 ClearScreen();
101 for(int i=from;i<from+lines&&i<size;i++) {
102 if(tab<map[i]->dim) {
103 if(i==size-1) {
104 if(tab<map[i]->dim-1)
105 OutputField(i-from,0,cols,sref(map[i]->line+tab,map[i]->dim-tab-1));
106 OutputField(i-from,map[i]->dim-tab-1,1,end_tag);
107 }
108 else {
109 OutputField(i-from,0,cols,sref(map[i]->line+tab,map[i]->dim-tab));
110 }
111 }
112 }
113 Reverse(1);
114 OutputField(lines,0,cols,caption);
115 Reverse(0);
116 MoveCursor(atline-from,atcol-tab);
117 Refresh();
118}
119
120void Editor::Move(int i,int j)
121{
122 atline+=i;
123 atcol+=j;
124 if(atline<0) atline=0; else if(atline>=size) atline=size-1;
125 if(atline<from) from=atline; else if(atline>=from+lines) from=atline+1-lines;
126 if(atcol<0) atcol=0; else if(atcol>=map[atline]->dim) atcol=map[atline]->dim-1;
127 if(atcol<tab) tab=atcol; else if(atcol>=tab+cols) tab=atcol+1-cols;
128}
129
130void Editor::Home()
131{
132 atline=from=atcol=tab=0;
133}
134
135void Editor::Navigate()
136{
137 int c;
138 while(1) {
139 Show();
140 switch(c=Input()) {
141 case KK_UP:
142 case 16:
143 Move(-1,0);
144 break;
145 case KK_DOWN:
146 case 14:
147 Move(1,0);
148 break;
149 case KK_LEFT:
150 case 2:
151 Move(0,-1); break;
152 case KK_RIGHT:
153 case 6:
154 Move(0,1);
155 break;
156 case KK_NPAGE:
157 Move(lines/2,0);
158 break;
159 case KK_PPAGE:
160 Move(-lines/2,0);
161 break;
162 case KK_HOME:
163 case 1:
164 Move(0,-map[atline]->dim);
165 break;
166 case KK_END:
167 case 5:
168 Move(0,map[atline]->dim);
169 break;
170 case 127:
171 case 4:
172 if(exclusive) Delete();
173 break;
174 case 8:
175 if(exclusive) Backspace();
176 break;
177 case 13:
178 if(exclusive) BreakLine();
179 break;
180 case KK_F(1):
181 if(exclusive) Insert('å');
182 break;
183 case KK_F(2):
184 if(exclusive) Insert('ä');
185 break;
186 case KK_F(3):
187 if(exclusive) Insert('ö');
188 break;
189 case 9:
190 if(exclusive) Insert('\t');
191 break;
192 default:
193 if(exclusive) if(c>=32&&c<127) Insert(c);
194 break;
195 case 27:
196 return;
197 }
198 }
199}
200
201void Editor::Insert(int c)
202{
203 if(map[atline]->Insert(atcol,c)) Move(0,1);
204}
205
206void Editor::BreakLine()
207{
208 if(size<MAXLINES) {
209 Line* p=map[atline]->Break(atcol);
210 memmove(map+atline+2,map+atline+1,sizeof(Line*)*(size-atline-1));
211 map[atline+1]=p;
212 size++;
213 Move(1,-atcol);
214 }
215}
216
217void Editor::Delete()
218{
219 if(map[atline]->dim-1>atcol) {
220 map[atline]->Delete(atcol);
221 }
222 else if(size-1>atline) {
223 delete map[atline];
224 memmove(map+atline,map+atline+1,sizeof(Line*)*(size-atline-1));
225 size--;
226 }
227}
228
229void Editor::Backspace()
230{
231 if(atcol>0) {
232 Move(0,-1);
233 map[atline]->Delete(atcol);
234 }
235 else if(atline>0) {
236 int pos=map[atline-1]->dim-1;
237 if(map[atline-1]->Append(map[atline])) {
238 delete map[atline];
239 memmove(map+atline,map+atline+1,sizeof(Line*)*(size-atline-1));
240 size--;
241 Move(-1,pos-atcol);
242 }
243 }
244}
245
246void Editor::Paste(const mstring& s)
247{
248 for(int i=0;i<s.size();i++) {
249 if(s[i]=='\n') BreakLine();
250 else if(s[i]!='\r') Insert(s[i]);
251 }
252 Home();
253}
254
255void Editor::Copy(mstring& s)
256{
257 s.clear();
258 for(int i=0;i<size;i++) {
259 s+=sref(map[i]->line,map[i]->dim-1);
260 if(i<size-1) s+='\n';
261 }
262}
diff --git a/src/hed/edit.h b/src/hed/edit.h
new file mode 100644
index 0000000..e6ae437
--- /dev/null
+++ b/src/hed/edit.h
@@ -0,0 +1,61 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef EDITH
21#define EDITH
22
23#include <mt/mstring.h>
24
25struct Editor {
26 static const int MAXLINES=1024;
27 static const int MAXCOLS=256;
28 struct Line {
29 Line();
30 Line(char* p,int s);
31 ~Line();
32 int Insert(int pos,char c);
33 int Append(const Line* p);
34 Line* Break(int pos);
35 void Delete(int pos);
36 char* line;
37 int dim;
38 };
39
40 Editor(const mstring& path,int ex);
41 ~Editor();
42
43 void Copy(mstring& s);
44 void Paste(const mstring& s);
45
46 void Show();
47 void Home();
48 void Move(int i,int j);
49 void Navigate();
50 void Insert(int c);
51 void BreakLine();
52 void Delete();
53 void Backspace();
54
55 mstring path,caption;
56 Line* map[MAXLINES];
57 int from,lines,atline,size;
58 int tab,cols,atcol,exclusive;
59};
60
61#endif
diff --git a/src/hed/hed.cc b/src/hed/hed.cc
new file mode 100644
index 0000000..dc469cc
--- /dev/null
+++ b/src/hed/hed.cc
@@ -0,0 +1,56 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "tables.h"
21#include "input.h"
22#include <unistd.h>
23
24static fp_stream merr(stderr);
25
26main(int argc,char* argv[])
27{
28 if(argc<2) {
29 merr<<"Usage: "<<argv[0]<<" <hdb> [exclusive]\n";
30 return -1;
31 }
32 char* path=argv[1];
33 int excl=argc>2?atoi(argv[2]):0;
34 mstring err;
35 sleep(1);
36 InitCurses();
37 Tables tab;
38 try {
39 tab.Open(path,excl);
40 tab.Setup(20);
41 tab.Navigate();
42 }
43 catch(const merror_t& e) {
44 err=e.desc;
45 }
46 catch(...) {
47 err="hdb: Unexpected error";
48 }
49 tab.Close();
50 EndCurses();
51 if(err.nempty()) {
52 merr<<err<<"\n";
53 sleep(2);
54 }
55 return 0;
56}
diff --git a/src/hed/input.cc b/src/hed/input.cc
new file mode 100644
index 0000000..4f2b008
--- /dev/null
+++ b/src/hed/input.cc
@@ -0,0 +1,107 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hed/input.h>
21#include <mt/mstring.h>
22#include <unistd.h>
23#include <poll.h>
24#include <curses.h>
25
26int Lines() { return LINES-1; }
27int Columns() { return COLS-1; }
28
29void ClearScreen() { erase(); }
30void MoveCursor(int i,int j) { move(i,j); }
31
32void InitCurses()
33{
34 initscr();
35 nodelay(stdscr,1);
36 raw();
37 noecho();
38 nonl();
39 keypad(stdscr,1);
40 intrflush(stdscr,FALSE);
41}
42
43void EndCurses()
44{
45 endwin();
46}
47
48void OutputField(int row,int col,int field,const sref& in)
49{
50 mstring tmp=in.left_first_of(cset_newl);
51 int cut=tmp.size()!=in.size();
52 if(tmp.size()<field) tmp.append(field-tmp.size(),' ');
53 if(cut||in.size()>field) { tmp.resize(field-1); tmp.append(1,'\\'); }
54 mvaddstr(row,col,(char*)tmp.c_str());
55}
56
57void Reverse(int n)
58{
59 if(n) attron(A_REVERSE); else attroff(A_REVERSE);
60}
61void Bold(int n)
62{
63 if(n) attron(A_BOLD); else attroff(A_BOLD);
64}
65
66void Refresh()
67{
68 refresh();
69}
70
71int RawInput() {
72 int c=getch();
73 if(c>0) return c;
74 struct pollfd ps={fileno(stdin),POLLIN,0};
75 poll(&ps,1,1000);
76 return getch();
77}
78
79int Input() {
80 int c=RawInput();
81#if 0
82 if(c==27) {
83 napms(1);
84 int c2=getch();
85 if(c2!=-1) {
86 switch(c2) {
87 default: return 0;
88 case 91:
89 switch(RawInput()) {
90 default: return 0;
91 case '2':
92 RawInput();
93 switch(RawInput()) {
94 default: return 0;
95 case 52: return RawInput()==122?KEY_HOME:0;
96 case 54: return RawInput()==122?KEY_PPAGE:0;
97 case 48: return RawInput()==122?KEY_END:0;
98 case 50: return RawInput()==122?KEY_NPAGE:0;
99 }
100 }
101 }
102 }
103 }
104#endif
105 return c;
106}
107
diff --git a/src/hed/input.h b/src/hed/input.h
new file mode 100644
index 0000000..76071ce
--- /dev/null
+++ b/src/hed/input.h
@@ -0,0 +1,52 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/stringref.h>
21
22#ifndef INPUTH
23#define INPUTH
24
25#define KK_DOWN 0402
26#define KK_UP 0403
27#define KK_LEFT 0404
28#define KK_RIGHT 0405
29#define KK_HOME 0406
30#define KK_F0 0410
31#define KK_F(n) (KK_F0+(n))
32#define KK_NPAGE 0522
33#define KK_PPAGE 0523
34#define KK_END 0550
35
36int Input();
37int RawInput();
38
39int Lines();
40int Columns();
41
42void ClearScreen();
43void MoveCursor(int i,int j);
44void OutputField(int row,int col,int field,const sref& p);
45void Reverse(int n);
46void Bold(int n);
47void Refresh();
48
49void InitCurses();
50void EndCurses();
51
52#endif
diff --git a/src/hed/tables.cc b/src/hed/tables.cc
new file mode 100644
index 0000000..c489e6f
--- /dev/null
+++ b/src/hed/tables.cc
@@ -0,0 +1,442 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "tables.h"
21#include "input.h"
22#include <string.h>
23#include <malloc.h>
24#include <stdio.h>
25
26const mstring star_tag="*";
27
28const int PAD=2;
29const mstring HELP=
30"Commands from record page:\n"
31"\n"
32"DEL - Delete record\n"
33"RET - Edit record\n"
34"n - New record\n"
35"s - Sort by table\n"
36"o - Order by table\n"
37"c - Check for duplicates\n"
38"f - Filename for map\n"
39"r - Remove table\n"
40"a - Add table\n";
41
42Tables::Tables() :
43 from(0),lines(Lines()-1),atline(0),writable(0),
44 tab(0),space(10),cols(Columns()),atcol(0),
45 lastfrom(-1),lasttab(-1),lastline(0),lastcol(0)
46{
47 dispcols=cols/space;
48}
49
50Tables::~Tables()
51{
52}
53
54void Tables::Setup(int sp)
55{
56 space=sp;
57 dispcols=cols/space;
58 Home();
59}
60
61void Tables::Show()
62{
63 if(db.remap()) {
64 lastfrom=-1;
65 caption.convert("%d, %d, %d, %d",
66 db.head()->filesize.get(),
67 db.head()->fatal.get(),
68 db.head()->major.get(),
69 db.head()->minor.get());
70 }
71 if(from!=lastfrom||tab!=lasttab) {
72 ClearScreen();
73 Bold(1);
74 for(int j=tab;j<tab+dispcols&&j<db.Tables();j++) {
75 if(j==db.Index()) {
76 OutputField(0,space*(j-tab),space-PAD-1,db.Table(j));
77 OutputField(0,space*(j-tab)+space-PAD-1,1,star_tag);
78 }
79 else {
80 OutputField(0,space*(j-tab),space-PAD,db.Table(j));
81 }
82 }
83 Bold(0);
84 for(int i=from;i<from+lines&&i<=db.size();i++) {
85 for(int j=tab;j<tab+dispcols&&j<=db.Tables();j++) {
86 sref tmp; if(i<db.size()&&j<db.Tables()) tmp=db(i,j);
87 if(i==atline&&j==atcol) Reverse(1); else Reverse(0);
88 OutputField(i+1-from,space*(j-tab),space-PAD,tmp);
89 if(i==atline&&j==atcol) Reverse(0);
90 }
91 }
92 Reverse(1);
93 OutputField(lines+1,1,cols-1,caption);
94 Reverse(0);
95 }
96 else {
97 int i=lastline,j=lastcol;
98 if(i>=0&&i<=db.size()&&j>=0&&j<=db.Tables()) {
99 sref tmp; if(i<db.size()&&j<db.Tables()) tmp=db(i,j);
100 OutputField(i+1-from,space*(j-tab),space-PAD,tmp);
101 }
102 i=atline; j=atcol;
103 if(i>=0&&i<=db.size()&&j>=0&&j<=db.Tables()) {
104 sref tmp; if(i<db.size()&&j<db.Tables()) tmp=db(i,j);
105 Reverse(1);
106 OutputField(i+1-from,space*(j-tab),space-PAD,tmp);
107 Reverse(0);
108 }
109 }
110 MoveCursor(lines+1,0);
111 Refresh();
112 lastline=atline;
113 lastcol=atcol;
114 lastfrom=from;
115 lasttab=tab;
116}
117
118void Tables::Home()
119{
120 atline=atcol=from=tab=0;
121}
122
123void Tables::Move(int i,int j)
124{
125 atline+=i;
126 if(atline>=db.size()) atline=db.size();
127 if(atline<0) atline=0;
128 if(atline>=from+lines) from=atline+1-lines;
129 if(atline<from) from=atline;
130 atcol+=j;
131 if(atcol>=db.Tables()) atcol=db.Tables();
132 if(atcol<0) atcol=0;
133 if(atcol>=tab+dispcols) tab=atcol+1-dispcols;
134 if(atcol<tab) tab=atcol;
135}
136
137void Tables::Insert()
138{
139 if(db.remap()) lastfrom=-1;
140 if(db.Tables()==0) return;
141 mstring tx,key,ttab=db.Table(db.Index());
142 tx.convert("%s - insert %s",path.c_str(),ttab.c_str());
143 Editor edit(tx,1);
144 edit.Paste("");
145 edit.Navigate();
146 edit.Copy(key);
147 int row=-1;
148 try {
149 spile list(db.Tables());
150 list[db.Index()]=key;
151 row=db.Insert(list,1);
152 if(row>=0) {
153 caption.convert("%s - added record",path.c_str());
154 Move(row-atline,0);
155 }
156 else {
157 caption.convert("%s - record nonunique - not added",path.c_str());
158 Move(0,0);
159 }
160 }
161 catch(const merror_t& e) {
162 caption=e.desc;
163 Move(0,0);
164 }
165 lastfrom=-1;
166}
167
168void Tables::Delete()
169{
170 if(db.remap()) lastfrom=-1;
171 if(atline<db.size()) {
172 db.Rem(atline);
173 Move(0,0);
174 lastfrom=-1;
175 }
176}
177
178void Tables::Navigate()
179{
180 int c;
181 while(1) {
182 Show();
183 switch(c=Input()) {
184 case KK_UP:
185 case 16:
186 Move(-1,0);
187 break;
188 case KK_DOWN:
189 case 14:
190 Move(1,0);
191 break;
192 case KK_LEFT:
193 case 2:
194 Move(0,-1); break;
195 case KK_RIGHT:
196 case 6:
197 case 9:
198 Move(0,1);
199 break;
200 case KK_NPAGE:
201 Move(lines/2,0);
202 break;
203 case KK_PPAGE:
204 Move(-lines/2,0);
205 break;
206 case KK_HOME:
207 case 1:
208 Move(0,-db.Tables());
209 break;
210 case KK_END:
211 case 5:
212 Move(0,db.Tables());
213 break;
214 case 127:
215 case 4:
216 if(writable) Delete();
217 break;
218 case 13:
219 Edit();
220 break;
221 case 's':
222 Sort();
223 break;
224 case 'o':
225 if(writable) Order();
226 break;
227 case 'c':
228 Check();
229 break;
230 case 'f':
231 FileName();
232 break;
233 case 'r':
234 if(writable) RemTable();
235 break;
236 case 'a':
237 if(writable) AddTable();
238 break;
239 case 'n':
240 if(writable) Insert();
241 break;
242 case 27:
243 if(Command()) break;
244 else return;
245 }
246
247 }
248}
249
250int Tables::Command()
251{
252 mstring tmp=caption;
253 caption="q (quit), s (save), h (help)";
254 lastfrom=-1;
255 Show();
256 switch(Input()) {
257 case 'q':
258 return 0;
259 case 's':
260 Save();
261 break;
262 case 'h':
263 Help();
264 break;
265 default:
266 caption=tmp;
267 break;
268 }
269 lastfrom=-1;
270 return 1;
271}
272
273void Tables::Help()
274{
275 Editor edit("help",0);
276 edit.Paste(HELP);
277 edit.Navigate();
278 lastfrom=-1;
279}
280
281void Tables::Edit()
282{
283 if(db.remap()) lastfrom=-1;
284 if(atline<db.size()&&atcol<db.Tables()) {
285 mstring tx;
286 tx.convert("%s - (%d,%d)",path.c_str(),atline+1,atcol+1);
287 Editor edit(tx,writable&&atcol!=db.Index());
288 edit.Paste(db(atline,atcol));
289 edit.Navigate();
290 edit.Copy(tx);
291 try {
292 if(writable) db.Set(atline,atcol,tx);
293 caption=path;
294 caption+=sref(" edited.");
295 }
296 catch(const merror_t& e) {
297 caption=e.desc;
298 }
299 catch(...) {
300 }
301 Move(0,0);
302 lastfrom=-1;
303 }
304}
305
306void Tables::Sort()
307{
308 if(db.remap()) lastfrom=-1;
309 if(atline<=db.size()&&atcol<db.Tables()) {
310 mstring tx=db.Compname();
311 Editor edit("compname",1);
312 edit.Paste(tx);
313 edit.Navigate();
314 edit.Copy(tx);
315 db.Sort(db.Table(atcol),tx);
316 mstring ttab=db.Table(db.Index());
317 caption.convert("%s sorted: %s %s",path.c_str(),ttab.c_str(),tx.c_str());
318 Move(0,0);
319 lastfrom=-1;
320 }
321}
322
323void Tables::Order()
324{
325 if(db.remap()) lastfrom=-1;
326 if(atline<=db.size()&&atcol<db.Tables()) {
327 mstring tx=db.Compname();
328 Editor edit("compname",1);
329 edit.Paste(tx);
330 edit.Navigate();
331 edit.Copy(tx);
332 db.Order(db.Table(atcol),tx);
333 mstring ttab=db.Table(db.Index());
334 caption.convert("%s ordered: %s %s",path.c_str(),ttab.c_str(),tx.c_str());
335 Move(0,0);
336 lastfrom=-1;
337 }
338}
339
340void Tables::Check()
341{
342 if(db.remap()) lastfrom=-1;
343 int idx=db.Index();
344 mswrite mm;
345 for(int i=0;i<db.size()-1;i++) {
346 if(db(i,idx)==db(i+1,idx)) mm<<db(i,idx)<<" duplicated\n";
347 }
348 if(mm.str().empty()) mm<<"Nothing duplicated\n";
349 Editor edit("check",0);
350 edit.Paste(mm.str());
351 edit.Navigate();
352 lastfrom=-1;
353}
354
355void Tables::FileName()
356{
357 if(db.remap()) lastfrom=-1;
358 mstring tx; tx.convert("%s - filename",path.c_str());
359 Editor edit(tx,1);
360 tx.convert("%s",path.c_str());
361 edit.Paste(tx);
362 edit.Navigate();
363 edit.Copy(tx);
364 path=tx;
365 lastfrom=-1;
366}
367
368void Tables::AddTable()
369{
370 if(db.remap()) lastfrom=-1;
371 mstring tx;
372 tx.convert("%s - add table (def: 2nd line)",path.c_str());
373 Editor edit(tx,1);
374 edit.Paste("");
375 edit.Navigate();
376 mstring tb;
377 edit.Copy(tb);
378 sref first,rest=tb;
379 Splitln(first,rest);
380 mstring name=first;
381 Splitln(first,rest);
382 int ok=-db.Tables();
383 db.InsertTable(atcol,name);
384 ok+=db.Tables();
385 if(ok) {
386 Move(0,0);
387 caption.convert("%s - added table",path.c_str());
388 }
389 else caption.convert("%s - not unique - table not added",path.c_str());
390 lastfrom=-1;
391}
392
393void Tables::RemTable()
394{
395 if(db.remap()) lastfrom=-1;
396 if(atcol<db.Tables()&&atcol!=db.Index()) {
397 db.RemTable(atcol);
398 Move(0,0);
399 caption.convert("%s - removed table",path.c_str());
400 }
401 else caption.convert("%s - key table - not removed",path.c_str());
402 lastfrom=-1;
403}
404
405void Tables::Open(const mstring& s,int ex)
406{
407 path=s;
408 writable=ex;
409 db.Open(s,ex);
410 if(ex) db.Saveas(path+sref(".bak"));
411 caption=s;
412 caption+=sref(" loaded");
413 if(ex) caption+=sref(" (exclusive)");
414 lastfrom=-1;
415}
416
417void Tables::Save()
418{
419 try {
420 db.Saveas(path);
421 caption=path;
422 caption+=sref(" saved");
423 }
424 catch(const merror_t& e) {
425 caption=e.desc;
426 }
427 lastfrom=-1;
428}
429
430void Tables::Close()
431{
432 if(writable) {
433 db.Close();
434 caption=path;
435 caption+=sref(" closed");
436 }
437 else {
438 caption=path;
439 caption+=sref(" readonly - not closed");
440 }
441 lastfrom=-1;
442}
diff --git a/src/hed/tables.h b/src/hed/tables.h
new file mode 100644
index 0000000..205ca63
--- /dev/null
+++ b/src/hed/tables.h
@@ -0,0 +1,61 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef TABLESH
21#define TABLESH
22
23#include <hed/edit.h>
24#include <hdb/db.h>
25
26struct Tables {
27 Tables();
28 ~Tables();
29
30 void Open(const mstring& path,int ex=0);
31 void Save();
32 void Close();
33
34 void Setup(int sp);
35
36 void Show();
37 void Home();
38 void Move(int i,int j);
39 void Navigate();
40 int Command();
41
42 void Sort();
43 void Order();
44 void Check();
45
46 void Edit();
47 void Insert();
48 void Delete();
49 void FileName();
50 void AddTable();
51 void RemTable();
52 void Help();
53
54 dbmap db;
55 mstring path,caption;
56 int from,lines,atline,writable;
57 int tab,space,cols,dispcols,dim,atcol;
58 int lastfrom,lasttab,lastline,lastcol;
59};
60
61#endif
diff --git a/src/hed/test.cc b/src/hed/test.cc
new file mode 100644
index 0000000..318334f
--- /dev/null
+++ b/src/hed/test.cc
@@ -0,0 +1,33 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "input.h"
21#include <stdio.h>
22
23main(int argc,char* argv[])
24{
25 InitCurses();
26 while(1) {
27 int c=RawInput();
28 fprintf(stderr,"%d\r\n",c);
29 if(c==27) break;
30 }
31 EndCurses();
32 return 0;
33}
diff --git a/src/http/http.h b/src/http/http.h
new file mode 100644
index 0000000..8bd4d23
--- /dev/null
+++ b/src/http/http.h
@@ -0,0 +1,144 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef HTTPH
21#define HTTPH
22
23#include <http/mime.h>
24
25///////////////////////////////////////////////////////////////////
26
27const mstring http_mime_default="application/octet-stream";
28
29const mstring HTTP_V10="HTTP/1.0";
30const mstring HTTP_V11="HTTP/1.1";
31
32///////////////////////////////////////////////////////////////////
33// Request types
34const mstring HTTP_OPTIONS="OPTIONS";
35const mstring HTTP_GET="GET";
36const mstring HTTP_HEAD="HEAD";
37const mstring HTTP_POST="POST";
38const mstring HTTP_PUT="PUT";
39const mstring HTTP_DELETE="DELETE";
40const mstring HTTP_TRACE="TRACE";
41const mstring HTTP_CONNECT="CONNECT";
42
43class httpReq : public HTTP {
44public:
45 httpReq();
46 httpReq(const sref& msg) { Init(msg); }
47
48 mstring method,uri,arg,version;
49 mstring auth,expect,from,host;
50 mstring if_match,if_mod,if_none,if_range,if_unmod;
51 mstring max_forwards,proxy,range;
52 mstring referer,te,user_agent;
53 sspile cookies;
54
55 void putHead(mstream& out) const;
56protected:
57 int Special(sref line);
58 int Handle(const sref& name,
59 const sref& rawval,
60 const sref& val,
61 const rrpile& opts);
62};
63
64///////////////////////////////////////////////////////////////////
65
66///////////////////////////////////////////////////////////////////
67// Informational 1xx
68const mstring HTTP_100="100 Continue";
69const mstring HTTP_101="101 Switching Protocols";
70// Successful 2xx
71const mstring HTTP_200="200 OK";
72const mstring HTTP_201="201 Created";
73const mstring HTTP_202="202 Accepted";
74const mstring HTTP_203="203 Non-Authoritative Information";
75const mstring HTTP_204="204 No Content";
76const mstring HTTP_205="205 Reset Content";
77const mstring HTTP_206="206 Partial Content";
78// Redirection 3xx
79const mstring HTTP_300="300 Multiple Choices";
80const mstring HTTP_301="301 Moved Permanently";
81const mstring HTTP_302="302 Found";
82const mstring HTTP_303="303 See Other";
83const mstring HTTP_304="304 Not Modified";
84const mstring HTTP_305="305 Use Proxy";
85const mstring HTTP_306="306 (Unused)";
86const mstring HTTP_307="307 Temporary Redirect";
87// Client Error 4xx
88const mstring HTTP_400="400 Bad Request";
89const mstring HTTP_401="401 Unauthorized";
90const mstring HTTP_402="402 Payment Required";
91const mstring HTTP_403="403 Forbidden";
92const mstring HTTP_404="404 Not Found";
93const mstring HTTP_405="405 Method Not Allowed";
94const mstring HTTP_406="406 Not Acceptable";
95const mstring HTTP_407="407 Proxy Authentication Required";
96const mstring HTTP_408="408 Request Timeout";
97const mstring HTTP_409="409 Conflict";
98const mstring HTTP_410="410 Gone";
99const mstring HTTP_411="411 Length Required";
100const mstring HTTP_412="412 Precondition Failed";
101const mstring HTTP_413="413 Request Entity Too Large";
102const mstring HTTP_414="414 Request-URI Too Long";
103const mstring HTTP_415="415 Unsupported Media Type";
104const mstring HTTP_416="416 Requested Range Not Satisfiable";
105const mstring HTTP_417="417 Expectation Failed";
106// Server Error 5xx
107const mstring HTTP_500="500 Internal Server Error";
108const mstring HTTP_501="501 Not Implemented";
109const mstring HTTP_502="502 Bad Gateway";
110const mstring HTTP_503="503 Service Unavailable";
111const mstring HTTP_504="504 Gateway Timeout";
112const mstring HTTP_505="505 HTTP Version Not Supported";
113
114struct cookie_t {
115 mstring name,val,options;
116 cookie_t() {}
117 cookie_t(const sref& n,const sref& v) : name(n),val(v) {}
118 cookie_t(const sref& n,const sref& v,const sref& o) :
119 name(n),val(v),options(o) {}
120};
121
122class httpResp : public HTTP {
123public:
124 httpResp();
125 httpResp(const sref& msg) { Init(msg); }
126
127 mstring version,status;
128 mstring age,etag,location;
129 mstring proxy_authent,retry,server,vary,authent;
130 msvec<cookie_t> set_cookies;
131
132 void putHead(mstream& out) const;
133protected:
134 int Special(sref line);
135 int Handle(const sref& name,
136 const sref& rawval,
137 const sref& val,
138 const rrpile& opts);
139};
140
141///////////////////////////////////////////////////////////////////
142
143#endif
144
diff --git a/src/http/mime.cc b/src/http/mime.cc
new file mode 100644
index 0000000..f6b3412
--- /dev/null
+++ b/src/http/mime.cc
@@ -0,0 +1,92 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <http/mime.h>
21
22HTTP::HTTP()
23{
24 connect="close";
25 pragma="no-cache";
26 date=httpTime(idate=Now());
27}
28
29int HTTP::Special(sref line)
30{
31 return 1;
32}
33
34int HTTP::Handle(const sref& name,
35 const sref& rawval,
36 const sref& val,
37 const rrpile& opts)
38{
39 if(Mime::Handle(name,rawval,val,opts)) return 1;
40 else if(eqn(name,cache_tag)) cache=val;
41 else if(eqn(name,connect_tag)) connect=val;
42 else if(eqn(name,date_tag)) date=val;
43 else if(eqn(name,pragma_tag)) pragma=val;
44 else if(eqn(name,trailer_tag)) trailer=val;
45 else if(eqn(name,trans_enc_tag)) trans_enc=val;
46 else if(eqn(name,upgrade_tag)) upgrade=val;
47 else if(eqn(name,via_tag)) via=val;
48 else if(eqn(name,warning_tag)) warning=val;
49 else if(eqn(name,allow_tag)) allow=val;
50 else if(eqn(name,cont_enc_tag)) cont_enc=val;
51 else if(eqn(name,cont_lang_tag)) cont_lang=val;
52 else if(eqn(name,cont_location_tag)) cont_location=val;
53 else if(eqn(name,cont_md5_tag)) cont_md5=val;
54 else if(eqn(name,cont_range_tag)) cont_range=val;
55 else if(eqn(name,expires_tag)) expires=val;
56 else if(eqn(name,lastmod_tag)) lastmod=val;
57 else if(eqn(name,accept_tag)) accept=val;
58 else if(eqn(name,accept_charset_tag)) accept_charset=val;
59 else if(eqn(name,accept_enc_tag)) accept_enc=val;
60 else if(eqn(name,accept_lang_tag)) accept_lang=val;
61 else if(eqn(name,accept_range_tag)) accept_range=val;
62 else return 0;
63 return 1;
64}
65
66void HTTP::putHead(mstream& out) const
67{
68 if(putval(out,cache_tag,cache)) putend(out);
69 if(putval(out,connect_tag,connect)) putend(out);
70 if(putval(out,date_tag,date)) putend(out);
71 if(putval(out,pragma_tag,pragma)) putend(out);
72 if(putval(out,trailer_tag,trailer)) putend(out);
73 if(putval(out,trans_enc_tag,trans_enc)) putend(out);
74 if(putval(out,upgrade_tag,upgrade)) putend(out);
75 if(putval(out,via_tag,via)) putend(out);
76 if(putval(out,warning_tag,warning)) putend(out);
77 if(putval(out,allow_tag,allow)) putend(out);
78 if(putval(out,cont_enc_tag,cont_enc)) putend(out);
79 if(putval(out,cont_lang_tag,cont_lang)) putend(out);
80 if(putval(out,cont_location_tag,cont_location)) putend(out);
81 if(putval(out,cont_md5_tag,cont_md5)) putend(out);
82 if(putval(out,cont_range_tag,cont_range)) putend(out);
83 if(putval(out,expires_tag,expires)) putend(out);
84 if(putval(out,lastmod_tag,lastmod)) putend(out);
85 if(putval(out,accept_tag,accept)) putend(out);
86 if(putval(out,accept_charset_tag,accept_charset)) putend(out);
87 if(putval(out,accept_enc_tag,accept_enc)) putend(out);
88 if(putval(out,accept_lang_tag,accept_lang)) putend(out);
89 if(putval(out,accept_range_tag,accept_range)) putend(out);
90 Mime::putHead(out);
91}
92
diff --git a/src/http/mime.h b/src/http/mime.h
new file mode 100644
index 0000000..85200cc
--- /dev/null
+++ b/src/http/mime.h
@@ -0,0 +1,99 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MIMEHTTPH
21#define MIMEHTTPH
22
23#include <mime/mime.h>
24#include <mt/dates.h>
25
26// Entity Headers
27const mstring allow_tag="Allow";
28const mstring accept_tag="Accept";
29const mstring accept_charset_tag="Accept-Charset";
30const mstring accept_enc_tag="Accept-Encoding";
31const mstring accept_lang_tag="Accept-Language";
32const mstring accept_range_tag="Accept-Ranges";
33const mstring cont_enc_tag="Content-Encoding";
34const mstring cont_lang_tag="Content-Language";
35const mstring cont_location_tag="Content-Location";
36const mstring cont_md5_tag="Content-MD5";
37const mstring cont_range_tag="Content-Range";
38const mstring expires_tag="Expires";
39const mstring lastmod_tag="Last-Modified";
40// General headers
41const mstring cache_tag="Cache-Control";
42const mstring connect_tag="Connection";
43const mstring date_tag="Date";
44const mstring pragma_tag="Pragma";
45const mstring trailer_tag="Trailer";
46const mstring trans_enc_tag="Transfer-Encoding";
47const mstring upgrade_tag="Upgrade";
48const mstring via_tag="Via";
49const mstring warning_tag="Warning";
50// Request headers
51const mstring auth_tag="Authorization";
52const mstring expect_tag="Expect";
53const mstring host_tag="Host";
54const mstring if_match_tag="If-Match";
55const mstring if_mod_tag="If-Modified-Since";
56const mstring if_none_tag="If-None-Match";
57const mstring if_range_tag="If-Range";
58const mstring if_unmod_tag="If-Unmodified-Since";
59const mstring max_forwards_tag="Max-Forwards";
60const mstring proxy_tag="Proxy-Authorization";
61const mstring range_tag="Range";
62const mstring referer_tag="Referer";
63const mstring te_tag="TE";
64const mstring user_agent_tag="User-Agent";
65const mstring cookie_tag="Cookie";
66// Response headers
67const mstring age_tag="Age";
68const mstring etag_tag="ETag";
69const mstring location_tag="Location";
70const mstring proxy_authent_tag="Proxy-Authenticate";
71const mstring retry_tag="Retry-After";
72const mstring server_tag="Server";
73const mstring vary_tag="Vary";
74const mstring authent_tag="WWW-Authenticate";
75const mstring set_cookie_tag="Set-Cookie";
76
77class HTTP : public Mime {
78public:
79 HTTP();
80 HTTP(const sref& msg) { Init(msg); }
81
82 mstring cache,connect,date,pragma;
83 mstring trailer,trans_enc,upgrade,via,warning;
84 mstring allow,cont_enc,cont_lang,cont_location;
85 mstring cont_md5,cont_range,expires,lastmod;
86 mstring accept,accept_charset,accept_enc,accept_lang,accept_range;
87
88 time_t idate;
89 void putHead(mstream& out) const;
90protected:
91 int Special(sref line);
92 int Handle(const sref& name,
93 const sref& rawval,
94 const sref& val,
95 const rrpile& opts);
96};
97
98#endif
99
diff --git a/src/http/req.cc b/src/http/req.cc
new file mode 100644
index 0000000..acb2105
--- /dev/null
+++ b/src/http/req.cc
@@ -0,0 +1,100 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <http/http.h>
21#include <mime/mailbox.h>
22
23httpReq::httpReq()
24{
25}
26
27int httpReq::Special(sref line)
28{
29 sref first,rest=line;
30 Split(first,rest);
31 method=first;
32 Split(first,rest);
33 uri=first;
34 arg.clear();
35 Split(first,rest);
36 version=first;
37 int pos=uri.find('?');
38 if(pos>=0) { arg=uri.right(pos+1); uri.resize(pos); }
39 return 1;
40}
41
42int httpReq::Handle(const sref& name,
43 const sref& rawval,
44 const sref& val,
45 const rrpile& opts)
46{
47 if(HTTP::Handle(name,rawval,val,opts)) return 1;
48 else if(eqn(name,auth_tag)) auth=val;
49 else if(eqn(name,expect_tag)) expect=val;
50 else if(eqn(name,from_tag)) from=val;
51 else if(eqn(name,host_tag)) host=val;
52 else if(eqn(name,if_match_tag)) if_match=val;
53 else if(eqn(name,if_mod_tag)) if_mod=val;
54 else if(eqn(name,if_none_tag)) if_none=val;
55 else if(eqn(name,if_range_tag)) if_range=val;
56 else if(eqn(name,if_unmod_tag)) if_unmod=val;
57 else if(eqn(name,max_forwards_tag)) max_forwards=val;
58 else if(eqn(name,proxy_tag)) proxy=val;
59 else if(eqn(name,range_tag)) range=val;
60 else if(eqn(name,referer_tag)) referer=val;
61 else if(eqn(name,te_tag)) te=val;
62 else if(eqn(name,user_agent_tag)) user_agent=val;
63 else if(eqn(name,cookie_tag)) {
64 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++)
65 cookies.push_back(sstring(p->first,p->second));
66 }
67 else return 0;
68 return 1;
69}
70
71void httpReq::putHead(mstream& out) const
72{
73 out<<method<<" "<<uri;
74 if(arg.nempty()) out<<"?"<<arg;
75 out<<" "<<version<<CRLF;
76 if(putval(out,auth_tag,auth)) putend(out);
77 if(putval(out,expect_tag,expect)) putend(out);
78 if(putval(out,from_tag,from)) putend(out);
79 if(putval(out,host_tag,host)) putend(out);
80 if(putval(out,if_match_tag,if_match)) putend(out);
81 if(putval(out,if_mod_tag,if_mod)) putend(out);
82 if(putval(out,if_none_tag,if_none)) putend(out);
83 if(putval(out,if_range_tag,if_range)) putend(out);
84 if(putval(out,if_unmod_tag,if_unmod)) putend(out);
85 if(putval(out,max_forwards_tag,max_forwards)) putend(out);
86 if(putval(out,proxy_tag,proxy)) putend(out);
87 if(putval(out,range_tag,range)) putend(out);
88 if(putval(out,referer_tag,referer)) putend(out);
89 if(putval(out,te_tag,te)) putend(out);
90 if(putval(out,user_agent_tag,user_agent)) putend(out);
91 HTTP::putHead(out);
92 if(!cookies.empty()) {
93 out<<cookie_tag<<": ";
94 for(sspile::const_iterator p=cookies.begin();p!=cookies.end();p++) {
95 if(p==cookies.begin()) putopt1(out,p->first,p->second);
96 else putopt(out,p->first,p->second);
97 }
98 putend(out);
99 }
100}
diff --git a/src/http/resp.cc b/src/http/resp.cc
new file mode 100644
index 0000000..aa7ed7b
--- /dev/null
+++ b/src/http/resp.cc
@@ -0,0 +1,79 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <http/http.h>
21
22httpResp::httpResp()
23{
24 server="HTCd/1.2 MT (Unix)";
25 version="HTTP/1.1";
26 status=HTTP_200;
27 mime_version.clear();
28 //accept="*/*";
29 //this is non-standard in response headers - now...
30}
31
32int httpResp::Special(sref line)
33{
34 version=First(line);
35 status=Rest(line);
36 return 1;
37}
38
39int httpResp::Handle(const sref& name,
40 const sref& rawval,
41 const sref& val,
42 const rrpile& opts)
43{
44 if(HTTP::Handle(name,rawval,val,opts)) return 1;
45 else if(eqn(name,age_tag)) age=val;
46 else if(eqn(name,etag_tag)) etag=val;
47 else if(eqn(name,location_tag)) location=val;
48 else if(eqn(name,proxy_authent_tag)) proxy_authent=val;
49 else if(eqn(name,retry_tag)) retry=val;
50 else if(eqn(name,server_tag)) server=val;
51 else if(eqn(name,vary_tag)) vary=val;
52 else if(eqn(name,authent_tag)) authent=val;
53 else if(eqn(name,set_cookie_tag)) {
54 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++)
55 set_cookies.push_back(cookie_t(p->first,p->second));
56 }
57 else return 0;
58 return 1;
59}
60
61void httpResp::putHead(mstream& out) const
62{
63 out<<version<<" "<<status<<CRLF;
64 if(putval(out,age_tag,age)) putend(out);
65 if(putval(out,etag_tag,etag)) putend(out);
66 if(putval(out,location_tag,location)) putend(out);
67 if(putval(out,proxy_authent_tag,proxy_authent)) putend(out);
68 if(putval(out,retry_tag,retry)) putend(out);
69 if(putval(out,server_tag,server)) putend(out);
70 if(putval(out,vary_tag,vary)) putend(out);
71 if(putval(out,authent_tag,authent)) putend(out);
72 HTTP::putHead(out);
73 for(msvec<cookie_t>::const_iterator p=set_cookies.begin();p!=set_cookies.end();p++) {
74 out<<set_cookie_tag<<": ";
75 putopt1(out,p->name,p->val);
76 if(p->options.nempty()) out<<"; "<<p->options;
77 putend(out);
78 }
79}
diff --git a/src/http/test.cc b/src/http/test.cc
new file mode 100644
index 0000000..59ac5c8
--- /dev/null
+++ b/src/http/test.cc
@@ -0,0 +1,28 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <http/http.h>
21#include <sys/stat.h>
22
23static fp_stream mout(stdout),merr(stderr);
24
25main(int argc,char* argv[])
26{
27 return 0;
28}
diff --git a/src/labat/README b/src/labat/README
new file mode 100644
index 0000000..96c3006
--- /dev/null
+++ b/src/labat/README
@@ -0,0 +1,49 @@
1
2KORT BESKRIVNING AV 'labat'
3===========================
4
5Indata ('atomctrl.dat') foer Al till 'labat' (Boer vara identisk med
6tidigare versioner).
7
813 0
910 40 0.2000
100.5000 0.00001 0.005
1130 0 0 0
125 2 0<--------------- 0, 1 & 2 foer respektive: lda, barth-hedin & GGA
13100 -84.5000 1 1 0 (knapp finns redan)
14200 -16.2450 1 1 0
15210 -5.3356 3 1 0
16300 -0.7812 1 1 0
17310 -0.2312 1 1 0
18100 -84.5000 1 1 0
19200 -16.2450 1 1 0
20210 -5.3356 3 1 0
21300 -0.7812 1 1 0
22310 -0.2312 0 1 0
23
24
25Skall ge foeljande resultat:
26(De utdata filer som finns i biblioteket aer fraan LDA-exemplet nedan)
27
28LDA
29
30 Total energy starts
31 iter: 22 total ch: 13.00 total en: -241.3129
32 Coulomb potential
33 NEW ITERATION
34
35GGA
36
37 Total energy starts
38 iter: 22 total ch: 13.00 total en: -242.3491
39 Coulomb potential
40 NEW ITERATION
41 Note: the following IEEE floating-point arithmetic exceptions
42 occurred and were never cleared; see ieee_flags(3M):
43 Inexact; Underflow;
44 Sun's implementation of IEEE arithmetic is discussed in
45 the Numerical Computation Guide.
46
47Inte saa snyggt med flyttalsfelen, men ...
48
49Utdatafilerna aer de som finns i detta bibliotek (samma som tidigare). \ No newline at end of file
diff --git a/src/labat/adensin.dat b/src/labat/adensin.dat
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/labat/adensin.dat
diff --git a/src/labat/adensout.dat b/src/labat/adensout.dat
new file mode 100644
index 0000000..7432734
--- /dev/null
+++ b/src/labat/adensout.dat
@@ -0,0 +1,402 @@
1 23 z,ion: 13. 0. jblock,nbl,c: 10 40 0.2000000
2 -0.1300000E+02 0.0000000E+00 0.0000000E+00 0.1388390E+04 0.0000000E+00
3 -0.2595549E+05 -0.2603599E+05 -0.2603598E+05 0.1388390E+04 0.5000000E-03
4 -0.1295549E+05 -0.1300223E+05 -0.1300222E+05 0.1370416E+04 0.1000000E-02
5 -0.8622160E+04 -0.8657409E+04 -0.8657408E+04 0.1352672E+04 0.1500000E-02
6 -0.6455499E+04 -0.6484424E+04 -0.6484424E+04 0.1335159E+04 0.2000000E-02
7 -0.5155505E+04 -0.5180875E+04 -0.5180875E+04 0.1317873E+04 0.2500000E-02
8 -0.4288846E+04 -0.4311748E+04 -0.4311748E+04 0.1300813E+04 0.3000000E-02
9 -0.3669807E+04 -0.3690957E+04 -0.3690957E+04 0.1283975E+04 0.3500000E-02
10 -0.3205532E+04 -0.3225349E+04 -0.3225349E+04 0.1267356E+04 0.4000000E-02
11 -0.2844432E+04 -0.2863203E+04 -0.2863204E+04 0.1250953E+04 0.4500000E-02
12 -0.2555556E+04 -0.2573482E+04 -0.2573482E+04 0.1234765E+04 0.5000000E-02
13 -0.2319206E+04 -0.2336431E+04 -0.2336432E+04 0.1218787E+04 0.5500000E-02
14 -0.2122252E+04 -0.2138886E+04 -0.2138887E+04 0.1203018E+04 0.6000000E-02
15 -0.1955601E+04 -0.1971728E+04 -0.1971729E+04 0.1187454E+04 0.6500000E-02
16 -0.1812762E+04 -0.1828448E+04 -0.1828448E+04 0.1172094E+04 0.7000000E-02
17 -0.1688971E+04 -0.1704268E+04 -0.1704268E+04 0.1156933E+04 0.7500000E-02
18 -0.1580658E+04 -0.1595610E+04 -0.1595610E+04 0.1141971E+04 0.8000000E-02
19 -0.1485089E+04 -0.1499732E+04 -0.1499732E+04 0.1127204E+04 0.8500000E-02
20 -0.1400144E+04 -0.1414506E+04 -0.1414507E+04 0.1112629E+04 0.9000000E-02
21 -0.1324143E+04 -0.1338250E+04 -0.1338250E+04 0.1098245E+04 0.9500000E-02
22 -0.1255747E+04 -0.1269619E+04 -0.1269619E+04 0.1084048E+04 0.1000000E-01
23 -0.1193866E+04 -0.1207523E+04 -0.1207523E+04 0.1070036E+04 0.1050000E-01
24 -0.1137615E+04 -0.1151072E+04 -0.1151072E+04 0.1056208E+04 0.1100000E-01
25 -0.1086258E+04 -0.1099528E+04 -0.1099528E+04 0.1042559E+04 0.1150000E-01
26 -0.1039185E+04 -0.1052280E+04 -0.1052281E+04 0.1029089E+04 0.1200000E-01
27 -0.9958791E+03 -0.1008811E+04 -0.1008812E+04 0.1015795E+04 0.1250000E-01
28 -0.9559090E+03 -0.9686865E+03 -0.9686870E+03 0.1002675E+04 0.1300000E-01
29 -0.9189016E+03 -0.9315332E+03 -0.9315337E+03 0.9897252E+03 0.1350000E-01
30 -0.8845416E+03 -0.8970348E+03 -0.8970353E+03 0.9769449E+03 0.1400000E-01
31 -0.8525533E+03 -0.8649147E+03 -0.8649152E+03 0.9643314E+03 0.1450000E-01
32 -0.8227014E+03 -0.8349372E+03 -0.8349377E+03 0.9518826E+03 0.1500000E-01
33 -0.7947774E+03 -0.8068931E+03 -0.8068936E+03 0.9395963E+03 0.1550000E-01
34 -0.7686024E+03 -0.7806030E+03 -0.7806036E+03 0.9274705E+03 0.1600000E-01
35 -0.7440157E+03 -0.7559058E+03 -0.7559063E+03 0.9155030E+03 0.1650000E-01
36 -0.7208790E+03 -0.7326628E+03 -0.7326633E+03 0.9036917E+03 0.1700000E-01
37 -0.6990662E+03 -0.7107476E+03 -0.7107481E+03 0.8920347E+03 0.1750000E-01
38 -0.6784689E+03 -0.6900513E+03 -0.6900518E+03 0.8805299E+03 0.1800000E-01
39 -0.6589867E+03 -0.6704735E+03 -0.6704740E+03 0.8691753E+03 0.1850000E-01
40 -0.6405335E+03 -0.6519276E+03 -0.6519282E+03 0.8579690E+03 0.1900000E-01
41 -0.6230283E+03 -0.6343326E+03 -0.6343331E+03 0.8469091E+03 0.1950000E-01
42 -0.6064018E+03 -0.6176191E+03 -0.6176196E+03 0.8359936E+03 0.2000000E-01
43 -0.5755291E+03 -0.5865791E+03 -0.5865796E+03 0.8145883E+03 0.2100000E-01
44 -0.5474761E+03 -0.5583670E+03 -0.5583675E+03 0.7937385E+03 0.2200000E-01
45 -0.5218688E+03 -0.5326084E+03 -0.5326089E+03 0.7734297E+03 0.2300000E-01
46 -0.4984078E+03 -0.5090028E+03 -0.5090033E+03 0.7536478E+03 0.2400000E-01
47 -0.4768298E+03 -0.4872860E+03 -0.4872865E+03 0.7343792E+03 0.2500000E-01
48 -0.4569235E+03 -0.4672462E+03 -0.4672466E+03 0.7156106E+03 0.2600000E-01
49 -0.4384975E+03 -0.4486914E+03 -0.4486919E+03 0.6973290E+03 0.2700000E-01
50 -0.4213989E+03 -0.4314685E+03 -0.4314689E+03 0.6795216E+03 0.2800000E-01
51 -0.4054850E+03 -0.4154341E+03 -0.4154346E+03 0.6621763E+03 0.2900000E-01
52 -0.3906428E+03 -0.4004751E+03 -0.4004756E+03 0.6452810E+03 0.3000000E-01
53 -0.3767633E+03 -0.3864822E+03 -0.3864826E+03 0.6288239E+03 0.3100000E-01
54 -0.3637615E+03 -0.3733700E+03 -0.3733704E+03 0.6127938E+03 0.3200000E-01
55 -0.3515527E+03 -0.3610536E+03 -0.3610541E+03 0.5971795E+03 0.3300000E-01
56 -0.3400718E+03 -0.3494678E+03 -0.3494682E+03 0.5819701E+03 0.3400000E-01
57 -0.3292517E+03 -0.3385452E+03 -0.3385456E+03 0.5671553E+03 0.3500000E-01
58 -0.3190419E+03 -0.3282353E+03 -0.3282357E+03 0.5527246E+03 0.3600000E-01
59 -0.3093885E+03 -0.3184839E+03 -0.3184843E+03 0.5386682E+03 0.3700000E-01
60 -0.3002519E+03 -0.3092515E+03 -0.3092519E+03 0.5249762E+03 0.3800000E-01
61 -0.2915882E+03 -0.3004938E+03 -0.3004942E+03 0.5116393E+03 0.3900000E-01
62 -0.2833661E+03 -0.2921795E+03 -0.2921799E+03 0.4986481E+03 0.4000000E-01
63 -0.2755491E+03 -0.2842721E+03 -0.2842724E+03 0.4859937E+03 0.4100000E-01
64 -0.2681122E+03 -0.2767465E+03 -0.2767468E+03 0.4736674E+03 0.4200000E-01
65 -0.2610252E+03 -0.2695722E+03 -0.2695725E+03 0.4616606E+03 0.4300000E-01
66 -0.2542678E+03 -0.2627292E+03 -0.2627295E+03 0.4499649E+03 0.4400000E-01
67 -0.2478145E+03 -0.2561915E+03 -0.2561919E+03 0.4385724E+03 0.4500000E-01
68 -0.2416489E+03 -0.2499431E+03 -0.2499434E+03 0.4274751E+03 0.4600000E-01
69 -0.2357492E+03 -0.2439618E+03 -0.2439621E+03 0.4166653E+03 0.4700000E-01
70 -0.2301022E+03 -0.2382345E+03 -0.2382347E+03 0.4061357E+03 0.4800000E-01
71 -0.2246890E+03 -0.2327421E+03 -0.2327424E+03 0.3958788E+03 0.4900000E-01
72 -0.2194988E+03 -0.2274741E+03 -0.2274743E+03 0.3858877E+03 0.5000000E-01
73 -0.2145153E+03 -0.2224138E+03 -0.2224140E+03 0.3761553E+03 0.5100000E-01
74 -0.2097297E+03 -0.2175525E+03 -0.2175527E+03 0.3666751E+03 0.5200000E-01
75 -0.2051276E+03 -0.2128759E+03 -0.2128761E+03 0.3574404E+03 0.5300000E-01
76 -0.2007019E+03 -0.2083766E+03 -0.2083768E+03 0.3484449E+03 0.5400000E-01
77 -0.1964400E+03 -0.2040421E+03 -0.2040423E+03 0.3396823E+03 0.5500000E-01
78 -0.1923359E+03 -0.1998664E+03 -0.1998666E+03 0.3311466E+03 0.5600000E-01
79 -0.1883786E+03 -0.1958384E+03 -0.1958385E+03 0.3228319E+03 0.5700000E-01
80 -0.1845630E+03 -0.1919531E+03 -0.1919532E+03 0.3147325E+03 0.5800000E-01
81 -0.1808793E+03 -0.1882005E+03 -0.1882006E+03 0.3068428E+03 0.5900000E-01
82 -0.1773235E+03 -0.1845771E+03 -0.1845772E+03 0.2991574E+03 0.6000000E-01
83 -0.1705632E+03 -0.1776836E+03 -0.1776837E+03 0.2843782E+03 0.6200000E-01
84 -0.1642440E+03 -0.1712338E+03 -0.1712338E+03 0.2703541E+03 0.6400000E-01
85 -0.1583165E+03 -0.1651794E+03 -0.1651794E+03 0.2570466E+03 0.6600000E-01
86 -0.1527544E+03 -0.1594933E+03 -0.1594932E+03 0.2444189E+03 0.6800000E-01
87 -0.1475181E+03 -0.1541359E+03 -0.1541358E+03 0.2324363E+03 0.7000000E-01
88 -0.1425878E+03 -0.1490873E+03 -0.1490871E+03 0.2210658E+03 0.7200000E-01
89 -0.1379313E+03 -0.1443151E+03 -0.1443149E+03 0.2102760E+03 0.7400000E-01
90 -0.1335335E+03 -0.1398043E+03 -0.1398041E+03 0.2000373E+03 0.7600000E-01
91 -0.1293678E+03 -0.1355281E+03 -0.1355278E+03 0.1903216E+03 0.7800000E-01
92 -0.1254229E+03 -0.1314751E+03 -0.1314748E+03 0.1811020E+03 0.8000000E-01
93 -0.1216763E+03 -0.1276228E+03 -0.1276224E+03 0.1723534E+03 0.8200000E-01
94 -0.1181193E+03 -0.1239626E+03 -0.1239621E+03 0.1640515E+03 0.8400000E-01
95 -0.1147332E+03 -0.1204754E+03 -0.1204749E+03 0.1561737E+03 0.8600000E-01
96 -0.1115112E+03 -0.1171545E+03 -0.1171540E+03 0.1486982E+03 0.8800000E-01
97 -0.1084373E+03 -0.1139839E+03 -0.1139833E+03 0.1416045E+03 0.9000000E-01
98 -0.1055064E+03 -0.1109583E+03 -0.1109576E+03 0.1348732E+03 0.9200000E-01
99 -0.1027046E+03 -0.1080640E+03 -0.1080632E+03 0.1284857E+03 0.9400000E-01
100 -0.1000279E+03 -0.1052968E+03 -0.1052960E+03 0.1224246E+03 0.9600000E-01
101 -0.9746453E+02 -0.1026449E+03 -0.1026440E+03 0.1166731E+03 0.9800000E-01
102 -0.9501135E+02 -0.1001051E+03 -0.1001042E+03 0.1112155E+03 0.1000000E+00
103 -0.9265802E+02 -0.9766714E+02 -0.9766614E+02 0.1060368E+03 0.1020000E+00
104 -0.9040218E+02 -0.9532851E+02 -0.9532743E+02 0.1011228E+03 0.1040000E+00
105 -0.8823479E+02 -0.9308017E+02 -0.9307902E+02 0.9645988E+02 0.1060000E+00
106 -0.8615402E+02 -0.9092026E+02 -0.9091904E+02 0.9203535E+02 0.1080000E+00
107 -0.8415194E+02 -0.8884081E+02 -0.8883952E+02 0.8783700E+02 0.1100000E+00
108 -0.8222714E+02 -0.8684041E+02 -0.8683904E+02 0.8385332E+02 0.1120000E+00
109 -0.8037265E+02 -0.8491201E+02 -0.8491058E+02 0.8007333E+02 0.1140000E+00
110 -0.7858737E+02 -0.8305453E+02 -0.8305302E+02 0.7648665E+02 0.1160000E+00
111 -0.7686513E+02 -0.8126175E+02 -0.8126016E+02 0.7308341E+02 0.1180000E+00
112 -0.7520512E+02 -0.7953283E+02 -0.7953116E+02 0.6985425E+02 0.1200000E+00
113 -0.7360184E+02 -0.7786223E+02 -0.7786049E+02 0.6679027E+02 0.1220000E+00
114 -0.7205467E+02 -0.7624934E+02 -0.7624752E+02 0.6388304E+02 0.1240000E+00
115 -0.7055874E+02 -0.7468921E+02 -0.7468732E+02 0.6112455E+02 0.1260000E+00
116 -0.6911358E+02 -0.7318138E+02 -0.7317942E+02 0.5850720E+02 0.1280000E+00
117 -0.6771482E+02 -0.7172144E+02 -0.7171940E+02 0.5602376E+02 0.1300000E+00
118 -0.6636214E+02 -0.7030904E+02 -0.7030693E+02 0.5366739E+02 0.1320000E+00
119 -0.6505161E+02 -0.6894022E+02 -0.6893804E+02 0.5143159E+02 0.1340000E+00
120 -0.6378303E+02 -0.6761476E+02 -0.6761251E+02 0.4931018E+02 0.1360000E+00
121 -0.6255284E+02 -0.6632897E+02 -0.6632666E+02 0.4729730E+02 0.1380000E+00
122 -0.6136093E+02 -0.6508333E+02 -0.6508094E+02 0.4538738E+02 0.1400000E+00
123 -0.5908087E+02 -0.6269912E+02 -0.6269661E+02 0.4185559E+02 0.1440000E+00
124 -0.5693497E+02 -0.6045311E+02 -0.6045048E+02 0.3867568E+02 0.1480000E+00
125 -0.5490706E+02 -0.5833048E+02 -0.5832774E+02 0.3581240E+02 0.1520000E+00
126 -0.5299250E+02 -0.5632548E+02 -0.5632265E+02 0.3323396E+02 0.1560000E+00
127 -0.5117801E+02 -0.5442476E+02 -0.5442185E+02 0.3091174E+02 0.1600000E+00
128 -0.4946011E+02 -0.5262454E+02 -0.5262154E+02 0.2881991E+02 0.1640000E+00
129 -0.4782780E+02 -0.5091357E+02 -0.5091048E+02 0.2693524E+02 0.1680000E+00
130 -0.4627845E+02 -0.4928903E+02 -0.4928587E+02 0.2523676E+02 0.1720000E+00
131 -0.4480284E+02 -0.4774149E+02 -0.4773825E+02 0.2370561E+02 0.1760000E+00
132 -0.4339903E+02 -0.4626887E+02 -0.4626555E+02 0.2232476E+02 0.1800000E+00
133 -0.4205917E+02 -0.4486324E+02 -0.4485982E+02 0.2107891E+02 0.1840000E+00
134 -0.4078187E+02 -0.4352312E+02 -0.4351958E+02 0.1995424E+02 0.1880000E+00
135 -0.3956040E+02 -0.4224178E+02 -0.4223812E+02 0.1893833E+02 0.1920000E+00
136 -0.3839376E+02 -0.4101827E+02 -0.4101445E+02 0.1801999E+02 0.1960000E+00
137 -0.3727616E+02 -0.3984685E+02 -0.3984286E+02 0.1718915E+02 0.2000000E+00
138 -0.3620690E+02 -0.3872696E+02 -0.3872277E+02 0.1643673E+02 0.2040000E+00
139 -0.3518093E+02 -0.3765367E+02 -0.3764925E+02 0.1575459E+02 0.2080000E+00
140 -0.3419781E+02 -0.3662670E+02 -0.3662203E+02 0.1513536E+02 0.2120000E+00
141 -0.3325310E+02 -0.3564173E+02 -0.3563679E+02 0.1457246E+02 0.2160000E+00
142 -0.3234658E+02 -0.3469866E+02 -0.3469345E+02 0.1405994E+02 0.2200000E+00
143 -0.3147428E+02 -0.3379361E+02 -0.3378811E+02 0.1359246E+02 0.2240000E+00
144 -0.3063618E+02 -0.3292656E+02 -0.3292078E+02 0.1316524E+02 0.2280000E+00
145 -0.2982870E+02 -0.3209392E+02 -0.3208788E+02 0.1277395E+02 0.2320000E+00
146 -0.2905197E+02 -0.3129569E+02 -0.3128939E+02 0.1241474E+02 0.2360000E+00
147 -0.2830276E+02 -0.3052846E+02 -0.3052194E+02 0.1208412E+02 0.2400000E+00
148 -0.2758130E+02 -0.2979222E+02 -0.2978550E+02 0.1177899E+02 0.2440000E+00
149 -0.2688467E+02 -0.2908371E+02 -0.2907684E+02 0.1149654E+02 0.2480000E+00
150 -0.2621319E+02 -0.2840292E+02 -0.2839591E+02 0.1123428E+02 0.2520000E+00
151 -0.2556417E+02 -0.2774676E+02 -0.2773967E+02 0.1098997E+02 0.2560000E+00
152 -0.2493803E+02 -0.2711527E+02 -0.2710811E+02 0.1076160E+02 0.2600000E+00
153 -0.2433227E+02 -0.2650557E+02 -0.2649839E+02 0.1054737E+02 0.2640000E+00
154 -0.2374739E+02 -0.2591779E+02 -0.2591062E+02 0.1034570E+02 0.2680000E+00
155 -0.2318108E+02 -0.2534931E+02 -0.2534218E+02 0.1015514E+02 0.2720000E+00
156 -0.2263386E+02 -0.2480036E+02 -0.2479329E+02 0.9974424E+01 0.2760000E+00
157 -0.2210359E+02 -0.2426857E+02 -0.2426158E+02 0.9802422E+01 0.2800000E+00
158 -0.2159086E+02 -0.2375429E+02 -0.2374740E+02 0.9638125E+01 0.2840000E+00
159 -0.2109364E+02 -0.2325536E+02 -0.2324860E+02 0.9480637E+01 0.2880000E+00
160 -0.2061255E+02 -0.2277227E+02 -0.2276563E+02 0.9329166E+01 0.2920000E+00
161 -0.2014569E+02 -0.2230305E+02 -0.2229655E+02 0.9183009E+01 0.2960000E+00
162 -0.1969372E+02 -0.2184864E+02 -0.2184228E+02 0.9041547E+01 0.3000000E+00
163 -0.1882853E+02 -0.2097648E+02 -0.2097040E+02 0.8770583E+01 0.3080000E+00
164 -0.1801631E+02 -0.2015516E+02 -0.2014935E+02 0.8512650E+01 0.3160000E+00
165 -0.1724865E+02 -0.1937739E+02 -0.1937184E+02 0.8264966E+01 0.3240000E+00
166 -0.1652664E+02 -0.1864364E+02 -0.1863834E+02 0.8025424E+01 0.3320000E+00
167 -0.1584281E+02 -0.1794675E+02 -0.1794167E+02 0.7792449E+01 0.3400000E+00
168 -0.1519858E+02 -0.1728820E+02 -0.1728334E+02 0.7564891E+01 0.3480000E+00
169 -0.1458727E+02 -0.1666144E+02 -0.1665678E+02 0.7341929E+01 0.3560000E+00
170 -0.1401053E+02 -0.1606820E+02 -0.1606374E+02 0.7122998E+01 0.3640000E+00
171 -0.1346233E+02 -0.1550256E+02 -0.1549828E+02 0.6907731E+01 0.3720000E+00
172 -0.1294447E+02 -0.1496642E+02 -0.1496230E+02 0.6695913E+01 0.3800000E+00
173 -0.1245148E+02 -0.1445440E+02 -0.1445044E+02 0.6487436E+01 0.3880000E+00
174 -0.1198522E+02 -0.1396847E+02 -0.1396467E+02 0.6282279E+01 0.3960000E+00
175 -0.1154073E+02 -0.1350375E+02 -0.1350009E+02 0.6080477E+01 0.4040000E+00
176 -0.1111990E+02 -0.1306222E+02 -0.1305869E+02 0.5882104E+01 0.4120000E+00
177 -0.1071819E+02 -0.1263941E+02 -0.1263602E+02 0.5687258E+01 0.4200000E+00
178 -0.1033748E+02 -0.1223727E+02 -0.1223401E+02 0.5496050E+01 0.4280000E+00
179 -0.9973640E+01 -0.1185173E+02 -0.1184860E+02 0.5308597E+01 0.4360000E+00
180 -0.9628498E+01 -0.1148468E+02 -0.1148168E+02 0.5125013E+01 0.4440000E+00
181 -0.9298274E+01 -0.1113239E+02 -0.1112950E+02 0.4945404E+01 0.4520000E+00
182 -0.8984746E+01 -0.1079667E+02 -0.1079390E+02 0.4769869E+01 0.4600000E+00
183 -0.8684450E+01 -0.1047411E+02 -0.1047145E+02 0.4598492E+01 0.4680000E+00
184 -0.8399097E+01 -0.1016644E+02 -0.1016390E+02 0.4431345E+01 0.4760000E+00
185 -0.8125514E+01 -0.9870523E+01 -0.9868100E+01 0.4268486E+01 0.4840000E+00
186 -0.7865330E+01 -0.9588022E+01 -0.9585710E+01 0.4109956E+01 0.4920000E+00
187 -0.7615641E+01 -0.9316053E+01 -0.9313852E+01 0.3955783E+01 0.5000000E+00
188 -0.7377991E+01 -0.9056183E+01 -0.9054090E+01 0.3805983E+01 0.5080000E+00
189 -0.7149719E+01 -0.8805770E+01 -0.8803785E+01 0.3660556E+01 0.5160000E+00
190 -0.6932283E+01 -0.8566289E+01 -0.8564411E+01 0.3519490E+01 0.5240000E+00
191 -0.6723244E+01 -0.8335320E+01 -0.8333546E+01 0.3382762E+01 0.5320000E+00
192 -0.6523973E+01 -0.8114244E+01 -0.8112573E+01 0.3250338E+01 0.5400000E+00
193 -0.6332238E+01 -0.7900843E+01 -0.7899275E+01 0.3122174E+01 0.5480000E+00
194 -0.6149320E+01 -0.7696410E+01 -0.7694942E+01 0.2998219E+01 0.5560000E+00
195 -0.5973176E+01 -0.7498912E+01 -0.7497543E+01 0.2878412E+01 0.5640000E+00
196 -0.5805002E+01 -0.7309553E+01 -0.7308282E+01 0.2762685E+01 0.5720000E+00
197 -0.5642928E+01 -0.7126472E+01 -0.7125297E+01 0.2650967E+01 0.5800000E+00
198 -0.5488069E+01 -0.6950791E+01 -0.6949710E+01 0.2543178E+01 0.5880000E+00
199 -0.5338712E+01 -0.6780801E+01 -0.6779813E+01 0.2439236E+01 0.5960000E+00
200 -0.5195893E+01 -0.6617551E+01 -0.6616654E+01 0.2339055E+01 0.6040000E+00
201 -0.5058045E+01 -0.6459456E+01 -0.6458647E+01 0.2242546E+01 0.6120000E+00
202 -0.4926129E+01 -0.6307589E+01 -0.6306867E+01 0.2149616E+01 0.6200000E+00
203 -0.4675622E+01 -0.6017721E+01 -0.6017166E+01 0.1974121E+01 0.6360000E+00
204 -0.4445670E+01 -0.5749102E+01 -0.5748706E+01 0.1811812E+01 0.6520000E+00
205 -0.4230526E+01 -0.5496313E+01 -0.5496065E+01 0.1661919E+01 0.6680000E+00
206 -0.4032409E+01 -0.5261418E+01 -0.5261306E+01 0.1523682E+01 0.6840000E+00
207 -0.3846543E+01 -0.5039689E+01 -0.5039701E+01 0.1396350E+01 0.7000000E+00
208 -0.3674838E+01 -0.4833033E+01 -0.4833155E+01 0.1279196E+01 0.7160000E+00
209 -0.3513323E+01 -0.4637484E+01 -0.4637700E+01 0.1171518E+01 0.7320000E+00
210 -0.3363636E+01 -0.4454678E+01 -0.4454972E+01 0.1072643E+01 0.7480000E+00
211 -0.3222470E+01 -0.4281309E+01 -0.4281661E+01 0.9819290E+00 0.7640000E+00
212 -0.3091222E+01 -0.4118767E+01 -0.4119158E+01 0.8987705E+00 0.7800000E+00
213 -0.2967138E+01 -0.3964298E+01 -0.3964704E+01 0.8225939E+00 0.7960000E+00
214 -0.2851403E+01 -0.3819079E+01 -0.3819475E+01 0.7528608E+00 0.8120000E+00
215 -0.2741725E+01 -0.3680812E+01 -0.3681172E+01 0.6890664E+00 0.8280000E+00
216 -0.2639104E+01 -0.3550493E+01 -0.3550789E+01 0.6307393E+00 0.8440000E+00
217 -0.2541630E+01 -0.3426204E+01 -0.3426405E+01 0.5774399E+00 0.8600000E+00
218 -0.2450147E+01 -0.3308787E+01 -0.3308860E+01 0.5287596E+00 0.8760000E+00
219 -0.2363061E+01 -0.3196638E+01 -0.3196549E+01 0.4843190E+00 0.8920000E+00
220 -0.2281084E+01 -0.3090467E+01 -0.3090180E+01 0.4437668E+00 0.9080000E+00
221 -0.2202882E+01 -0.2988933E+01 -0.2988411E+01 0.4067778E+00 0.9240000E+00
222 -0.2129056E+01 -0.2892634E+01 -0.2891840E+01 0.3730519E+00 0.9400000E+00
223 -0.2058489E+01 -0.2800443E+01 -0.2799340E+01 0.3423121E+00 0.9560000E+00
224 -0.1991689E+01 -0.2712863E+01 -0.2711416E+01 0.3143033E+00 0.9720000E+00
225 -0.1927716E+01 -0.2628944E+01 -0.2627118E+01 0.2887906E+00 0.9880000E+00
226 -0.1867000E+01 -0.2549106E+01 -0.2546871E+01 0.2655581E+00 0.1004000E+01
227 -0.1808751E+01 -0.2472542E+01 -0.2469873E+01 0.2444075E+00 0.1020000E+01
228 -0.1753332E+01 -0.2399598E+01 -0.2396476E+01 0.2251568E+00 0.1036000E+01
229 -0.1700075E+01 -0.2329581E+01 -0.2325996E+01 0.2076389E+00 0.1052000E+01
230 -0.1649290E+01 -0.2262775E+01 -0.2258726E+01 0.1917008E+00 0.1068000E+01
231 -0.1600410E+01 -0.2198578E+01 -0.2194075E+01 0.1772025E+00 0.1084000E+01
232 -0.1553701E+01 -0.2137216E+01 -0.2132284E+01 0.1640157E+00 0.1100000E+01
233 -0.1508678E+01 -0.2078159E+01 -0.2072837E+01 0.1520230E+00 0.1116000E+01
234 -0.1465571E+01 -0.2021586E+01 -0.2015928E+01 0.1411172E+00 0.1132000E+01
235 -0.1423964E+01 -0.1967027E+01 -0.1961103E+01 0.1312003E+00 0.1148000E+01
236 -0.1384055E+01 -0.1914622E+01 -0.1908519E+01 0.1221829E+00 0.1164000E+01
237 -0.1345487E+01 -0.1863954E+01 -0.1857772E+01 0.1139832E+00 0.1180000E+01
238 -0.1308434E+01 -0.1815136E+01 -0.1808990E+01 0.1065267E+00 0.1196000E+01
239 -0.1272584E+01 -0.1767803E+01 -0.1761817E+01 0.9974546E-01 0.1212000E+01
240 -0.1238091E+01 -0.1722058E+01 -0.1716363E+01 0.9357756E-01 0.1228000E+01
241 -0.1204683E+01 -0.1677566E+01 -0.1672305E+01 0.8796654E-01 0.1244000E+01
242 -0.1172496E+01 -0.1634699E+01 -0.1629912E+01 0.8286100E-01 0.1260000E+01
243 -0.1111034E+01 -0.1552141E+01 -0.1548759E+01 0.7398329E-01 0.1292000E+01
244 -0.1053781E+01 -0.1473828E+01 -0.1472483E+01 0.6661834E-01 0.1324000E+01
245 -0.9997888E+00 -0.1400499E+01 -0.1401124E+01 0.6049638E-01 0.1356000E+01
246 -0.9493000E+00 -0.1332437E+01 -0.1334992E+01 0.5539439E-01 0.1388000E+01
247 -0.9015512E+00 -0.1269951E+01 -0.1273997E+01 0.5112811E-01 0.1420000E+01
248 -0.8567650E+00 -0.1213951E+01 -0.1218776E+01 0.4754545E-01 0.1452000E+01
249 -0.8143093E+00 -0.1164221E+01 -0.1168861E+01 0.4452084E-01 0.1484000E+01
250 -0.7743937E+00 -0.1120850E+01 -0.1124218E+01 0.4195074E-01 0.1516000E+01
251 -0.7364808E+00 -0.1082695E+01 -0.1083725E+01 0.3974985E-01 0.1548000E+01
252 -0.7007718E+00 -0.1049020E+01 -0.1046827E+01 0.3784805E-01 0.1580000E+01
253 -0.6667987E+00 -0.1018339E+01 -0.1012329E+01 0.3618785E-01 0.1612000E+01
254 -0.6347570E+00 -0.9899549E+00 -0.9798729E+00 0.3472230E-01 0.1644000E+01
255 -0.6042310E+00 -0.9628122E+00 -0.9487126E+00 0.3341320E-01 0.1676000E+01
256 -0.5754114E+00 -0.9367280E+00 -0.9189042E+00 0.3222963E-01 0.1708000E+01
257 -0.5479233E+00 -0.9111737E+00 -0.8900652E+00 0.3114664E-01 0.1740000E+01
258 -0.5219526E+00 -0.8863284E+00 -0.8624346E+00 0.3014423E-01 0.1772000E+01
259 -0.4971574E+00 -0.8619231E+00 -0.8357382E+00 0.2920641E-01 0.1804000E+01
260 -0.4737188E+00 -0.8382449E+00 -0.8102159E+00 0.2832052E-01 0.1836000E+01
261 -0.4513220E+00 -0.8150882E+00 -0.7855948E+00 0.2747653E-01 0.1868000E+01
262 -0.4301432E+00 -0.7927277E+00 -0.7620769E+00 0.2666662E-01 0.1900000E+01
263 -0.4098909E+00 -0.7709543E+00 -0.7393852E+00 0.2588470E-01 0.1932000E+01
264 -0.3907354E+00 -0.7500038E+00 -0.7176972E+00 0.2512610E-01 0.1964000E+01
265 -0.3724062E+00 -0.7296567E+00 -0.6967459E+00 0.2438728E-01 0.1996000E+01
266 -0.3550673E+00 -0.7101160E+00 -0.6766974E+00 0.2366561E-01 0.2028000E+01
267 -0.3384670E+00 -0.6911601E+00 -0.6573023E+00 0.2295918E-01 0.2060000E+01
268 -0.3227623E+00 -0.6729690E+00 -0.6387208E+00 0.2226662E-01 0.2092000E+01
269 -0.3077190E+00 -0.6553265E+00 -0.6207223E+00 0.2158701E-01 0.2124000E+01
270 -0.2934872E+00 -0.6383971E+00 -0.6034618E+00 0.2091978E-01 0.2156000E+01
271 -0.2798485E+00 -0.6219742E+00 -0.5867265E+00 0.2026461E-01 0.2188000E+01
272 -0.2669456E+00 -0.6062106E+00 -0.5706650E+00 0.1962136E-01 0.2220000E+01
273 -0.2545754E+00 -0.5909118E+00 -0.5550803E+00 0.1899002E-01 0.2252000E+01
274 -0.2428730E+00 -0.5762208E+00 -0.5401141E+00 0.1837071E-01 0.2284000E+01
275 -0.2316495E+00 -0.5619556E+00 -0.5255836E+00 0.1776357E-01 0.2316000E+01
276 -0.2210324E+00 -0.5482501E+00 -0.5116226E+00 0.1716881E-01 0.2348000E+01
277 -0.2108462E+00 -0.5349346E+00 -0.4980613E+00 0.1658662E-01 0.2380000E+01
278 -0.2012111E+00 -0.5221348E+00 -0.4850254E+00 0.1601722E-01 0.2412000E+01
279 -0.1919639E+00 -0.5096924E+00 -0.4723569E+00 0.1546081E-01 0.2444000E+01
280 -0.1832175E+00 -0.4977253E+00 -0.4601740E+00 0.1491755E-01 0.2476000E+01
281 -0.1748207E+00 -0.4860862E+00 -0.4483281E+00 0.1438759E-01 0.2508000E+01
282 -0.1668792E+00 -0.4748784E+00 -0.4369330E+00 0.1387106E-01 0.2540000E+01
283 -0.1519300E+00 -0.4533747E+00 -0.4150697E+00 0.1287855E-01 0.2604000E+01
284 -0.1385606E+00 -0.4334250E+00 -0.3947919E+00 0.1194032E-01 0.2668000E+01
285 -0.1262177E+00 -0.4144804E+00 -0.3755696E+00 0.1105607E-01 0.2732000E+01
286 -0.1151813E+00 -0.3968488E+00 -0.3576985E+00 0.1022509E-01 0.2796000E+01
287 -0.1049818E+00 -0.3800720E+00 -0.3407204E+00 0.9446185E-02 0.2860000E+01
288 -0.9586293E-01 -0.3644036E+00 -0.3248878E+00 0.8717863E-02 0.2924000E+01
289 -0.8742742E-01 -0.3494545E+00 -0.3098101E+00 0.8038327E-02 0.2988000E+01
290 -0.7988579E-01 -0.3354404E+00 -0.2957027E+00 0.7405589E-02 0.3052000E+01
291 -0.7290285E-01 -0.3220310E+00 -0.2822344E+00 0.6817501E-02 0.3116000E+01
292 -0.6665946E-01 -0.3094103E+00 -0.2695892E+00 0.6271827E-02 0.3180000E+01
293 -0.6087338E-01 -0.2972994E+00 -0.2574886E+00 0.5766276E-02 0.3244000E+01
294 -0.5569926E-01 -0.2858555E+00 -0.2460910E+00 0.5298551E-02 0.3308000E+01
295 -0.5089992E-01 -0.2748450E+00 -0.2351639E+00 0.4866365E-02 0.3372000E+01
296 -0.4660712E-01 -0.2644031E+00 -0.2248447E+00 0.4467480E-02 0.3436000E+01
297 -0.4262181E-01 -0.2543353E+00 -0.2149415E+00 0.4099715E-02 0.3500000E+01
298 -0.3905594E-01 -0.2447585E+00 -0.2055748E+00 0.3760969E-02 0.3564000E+01
299 -0.3574266E-01 -0.2355122E+00 -0.1965873E+00 0.3449222E-02 0.3628000E+01
300 -0.3277686E-01 -0.2266977E+00 -0.1880852E+00 0.3162550E-02 0.3692000E+01
301 -0.3001881E-01 -0.2181828E+00 -0.1799408E+00 0.2899126E-02 0.3756000E+01
302 -0.2754880E-01 -0.2100555E+00 -0.1722479E+00 0.2657222E-02 0.3820000E+01
303 -0.2524987E-01 -0.2022069E+00 -0.1649028E+00 0.2435210E-02 0.3884000E+01
304 -0.2318989E-01 -0.1947127E+00 -0.1579876E+00 0.2231562E-02 0.3948000E+01
305 -0.2127099E-01 -0.1874827E+00 -0.1514179E+00 0.2044845E-02 0.4012000E+01
306 -0.1955048E-01 -0.1805814E+00 -0.1452648E+00 0.1873723E-02 0.4076000E+01
307 -0.1794647E-01 -0.1739333E+00 -0.1394586E+00 0.1716950E-02 0.4140000E+01
308 -0.1650734E-01 -0.1675924E+00 -0.1340594E+00 0.1573368E-02 0.4204000E+01
309 -0.1516454E-01 -0.1614947E+00 -0.1290088E+00 0.1441900E-02 0.4268000E+01
310 -0.1395892E-01 -0.1556847E+00 -0.1243564E+00 0.1321551E-02 0.4332000E+01
311 -0.1283309E-01 -0.1501076E+00 -0.1200515E+00 0.1211399E-02 0.4396000E+01
312 -0.1182151E-01 -0.1447993E+00 -0.1161341E+00 0.1110594E-02 0.4460000E+01
313 -0.1087613E-01 -0.1397124E+00 -0.1125590E+00 0.1018350E-02 0.4524000E+01
314 -0.1002603E-01 -0.1348758E+00 -0.1093569E+00 0.9339444E-03 0.4588000E+01
315 -0.9230932E-02 -0.1302480E+00 -0.1064866E+00 0.8567129E-03 0.4652000E+01
316 -0.8515411E-02 -0.1258518E+00 -0.1039701E+00 0.7860439E-03 0.4716000E+01
317 -0.7845663E-02 -0.1216511E+00 -0.1017683E+00 0.7213763E-03 0.4780000E+01
318 -0.7242465E-02 -0.1176638E+00 -0.9989635E-01 0.6621957E-03 0.4844000E+01
319 -0.6677425E-02 -0.1138581E+00 -0.9831432E-01 0.6080303E-03 0.4908000E+01
320 -0.6168124E-02 -0.1102479E+00 -0.9703127E-01 0.5584483E-03 0.4972000E+01
321 -0.5690686E-02 -0.1068102E+00 -0.9602603E-01 0.5130545E-03 0.5036000E+01
322 -0.5260000E-02 -0.1034991E+00 -0.9505341E-01 0.4714874E-03 0.5100000E+01
323 -0.4477611E-02 -0.9738560E-01 -0.9418036E-01 0.3985415E-03 0.5228000E+01
324 -0.3839408E-02 -0.9208111E-01 -0.9434847E-01 0.3372963E-03 0.5356000E+01
325 -0.3276214E-02 -0.8712605E-01 -0.9447003E-01 0.2858183E-03 0.5484000E+01
326 -0.2815384E-02 -0.8275498E-01 -0.9470701E-01 0.2425016E-03 0.5612000E+01
327 -0.2407649E-02 -0.7880597E-01 -0.9443366E-01 0.2060095E-03 0.5740000E+01
328 -0.2073021E-02 -0.7530793E-01 -0.9316562E-01 0.1752304E-03 0.5868000E+01
329 -0.1776219E-02 -0.7218882E-01 -0.9039150E-01 0.1492396E-03 0.5996000E+01
330 -0.1531937E-02 -0.6944847E-01 -0.8585081E-01 0.1272676E-03 0.6124000E+01
331 -0.1314767E-02 -0.6703940E-01 -0.7957347E-01 0.1086725E-03 0.6252000E+01
332 -0.1135546E-02 -0.6495564E-01 -0.7195440E-01 0.9291864E-04 0.6380000E+01
333 -0.9758780E-03 -0.6316060E-01 -0.6356518E-01 0.7955734E-04 0.6508000E+01
334 -0.8437878E-03 -0.6164610E-01 -0.5502886E-01 0.6821233E-04 0.6636000E+01
335 -0.7258824E-03 -0.6038230E-01 -0.4683629E-01 0.5856753E-04 0.6764000E+01
336 -0.6281358E-03 -0.5936004E-01 -0.3932925E-01 0.5035729E-04 0.6892000E+01
337 -0.5407396E-03 -0.5855440E-01 -0.3267298E-01 0.4335820E-04 0.7020000E+01
338 -0.4681628E-03 -0.5795552E-01 -0.2692364E-01 0.3738247E-04 0.7148000E+01
339 -0.4031804E-03 -0.5754156E-01 -0.2204530E-01 0.3227223E-04 0.7276000E+01
340 -0.3491509E-03 -0.5730096E-01 -0.1796735E-01 0.2789478E-04 0.7404000E+01
341 -0.3007215E-03 -0.5721191E-01 -0.1459036E-01 0.2413855E-04 0.7532000E+01
342 -0.2604263E-03 -0.5725804E-01 -0.1181837E-01 0.2090971E-04 0.7660000E+01
343 -0.2242786E-03 -0.5741189E-01 -0.9553631E-02 0.1812931E-04 0.7788000E+01
344 -0.1941961E-03 -0.5764507E-01 -0.7713419E-02 0.1573087E-04 0.7916000E+01
345 -0.1671959E-03 -0.5791416E-01 -0.6221017E-02 0.1365834E-04 0.8044000E+01
346 -0.1447322E-03 -0.5816658E-01 -0.5015104E-02 0.1186447E-04 0.8172000E+01
347 -0.1245648E-03 -0.5832927E-01 -0.4040885E-02 0.1030935E-04 0.8300000E+01
348 -0.1077970E-03 -0.5831462E-01 -0.3255975E-02 0.8959263E-05 0.8428000E+01
349 -0.9274227E-04 -0.5801756E-01 -0.2623018E-02 0.7785684E-05 0.8556000E+01
350 -0.8023715E-04 -0.5733050E-01 -0.2113778E-02 0.6764473E-05 0.8684000E+01
351 -0.6901030E-04 -0.5615555E-01 -0.1703398E-02 0.5875158E-05 0.8812000E+01
352 -0.5969468E-04 -0.5442941E-01 -0.1373437E-02 0.5100342E-05 0.8940000E+01
353 -0.5133223E-04 -0.5213802E-01 -0.1107546E-02 0.4425190E-05 0.9068000E+01
354 -0.4440046E-04 -0.4932734E-01 -0.8937972E-03 0.3836992E-05 0.9196000E+01
355 -0.3817843E-04 -0.4609416E-01 -0.7214846E-03 0.3324793E-05 0.9324000E+01
356 -0.3302527E-04 -0.4256982E-01 -0.5829321E-03 0.2879091E-05 0.9452000E+01
357 -0.2839972E-04 -0.3889556E-01 -0.4711485E-03 0.2491593E-05 0.9580000E+01
358 -0.2457111E-04 -0.3520294E-01 -0.3811972E-03 0.2155026E-05 0.9708000E+01
359 -0.2113409E-04 -0.3160316E-01 -0.3085691E-03 0.1862988E-05 0.9836000E+01
360 -0.1829022E-04 -0.2817333E-01 -0.2499891E-03 0.1609836E-05 0.9964000E+01
361 -0.1573666E-04 -0.2497170E-01 -0.2027310E-03 0.1390594E-05 0.1009200E+02
362 -0.1362402E-04 -0.2210784E-01 -0.1652864E-03 0.1200876E-05 0.1022000E+02
363 -0.1003603E-04 -0.1699821E-01 -0.1084125E-03 0.8950437E-06 0.1047600E+02
364 -0.7578580E-05 -0.1282903E-01 -0.7098972E-04 0.6668682E-06 0.1073200E+02
365 -0.5593245E-05 -0.9722369E-02 -0.4731680E-04 0.4969029E-06 0.1098800E+02
366 -0.4231523E-05 -0.7312414E-02 -0.3158502E-04 0.3703987E-06 0.1124400E+02
367 -0.3129260E-05 -0.5490480E-02 -0.2113629E-04 0.2762676E-06 0.1150000E+02
368 -0.2371758E-05 -0.4114605E-02 -0.1424593E-04 0.2062147E-06 0.1175600E+02
369 -0.1757350E-05 -0.3081342E-02 -0.9610490E-05 0.1540572E-06 0.1201200E+02
370 -0.1334218E-05 -0.2306980E-02 -0.6544879E-05 0.1151978E-06 0.1226800E+02
371 -0.9903398E-06 -0.1727497E-02 -0.4462305E-05 0.8622252E-07 0.1252400E+02
372 -0.7530195E-06 -0.1294164E-02 -0.3079240E-05 0.6459763E-07 0.1278000E+02
373 -0.5597898E-06 -0.9701390E-03 -0.2129932E-05 0.4844297E-07 0.1303600E+02
374 -0.4261723E-06 -0.7278158E-03 -0.1496628E-05 0.3636283E-07 0.1329200E+02
375 -0.3171916E-06 -0.5464862E-03 -0.1056886E-05 0.2732050E-07 0.1354800E+02
376 -0.2416965E-06 -0.4107180E-03 -0.7620499E-06 0.2054534E-07 0.1380400E+02
377 -0.1800252E-06 -0.3089713E-03 -0.5546206E-06 0.1546393E-07 0.1406000E+02
378 -0.1372363E-06 -0.2326598E-03 -0.4147161E-06 0.1164921E-07 0.1431600E+02
379 -0.1022343E-06 -0.1753656E-03 -0.3147953E-06 0.8782751E-08 0.1457200E+02
380 -0.7791838E-07 -0.1323115E-03 -0.2468912E-06 0.6626895E-08 0.1482800E+02
381 -0.5800449E-07 -0.9992339E-04 -0.1975415E-06 0.5004068E-08 0.1508400E+02
382 -0.4415836E-07 -0.7553729E-04 -0.1636582E-06 0.3781453E-08 0.1534000E+02
383 -0.3280884E-07 -0.5715659E-04 -0.1385254E-06 0.2859604E-08 0.1559600E+02
384 -0.2491523E-07 -0.4329052E-04 -0.1210146E-06 0.2163988E-08 0.1585200E+02
385 -0.1844174E-07 -0.3281947E-04 -0.1077074E-06 0.1638689E-08 0.1610800E+02
386 -0.1394203E-07 -0.2490580E-04 -0.9823689E-07 0.1241718E-08 0.1636400E+02
387 -0.1025218E-07 -0.1891908E-04 -0.9082938E-07 0.9415138E-09 0.1662000E+02
388 -0.7692438E-08 -0.1438669E-04 -0.8539718E-07 0.7143355E-09 0.1687600E+02
389 -0.5595531E-08 -0.1095216E-04 -0.8100327E-07 0.5423066E-09 0.1713200E+02
390 -0.4147089E-08 -0.8347732E-05 -0.7765120E-07 0.4119569E-09 0.1738800E+02
391 -0.2963576E-08 -0.6371051E-05 -0.7483810E-07 0.3131281E-09 0.1764400E+02
392 -0.2152832E-08 -0.4869813E-05 -0.7258860E-07 0.2381534E-09 0.1790000E+02
393 -0.1493862E-08 -0.3728723E-05 -0.7063156E-07 0.1812426E-09 0.1815600E+02
394 -0.1049466E-08 -0.2860763E-05 -0.6898356E-07 0.1380194E-09 0.1841200E+02
395 -0.6919968E-09 -0.2200249E-05 -0.6751792E-07 0.1051739E-09 0.1866800E+02
396 -0.4581243E-09 -0.1696551E-05 -0.6621113E-07 0.8020129E-10 0.1892400E+02
397 -0.2739404E-09 -0.1314388E-05 -0.6501141E-07 0.6120459E-10 0.1918000E+02
398 -0.1609299E-09 -0.1017272E-05 -0.6392195E-07 0.4674641E-10 0.1943600E+02
399 -0.7618943E-10 -0.8068822E-06 -0.6289578E-07 0.3573691E-10 0.1969200E+02
400 -0.3236183E-10 -0.6020435E-06 -0.6193826E-07 0.2734932E-10 0.1994800E+02
401 -0.4470313E-11 -0.5522402E-06 -0.6102801E-07 0.2095607E-10 0.2020400E+02
402 0.0000000E+00 -0.4950088E-06 -0.6016242E-07 0.1608056E-10 0.2046000E+02
diff --git a/src/labat/apotin.dat b/src/labat/apotin.dat
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/labat/apotin.dat
diff --git a/src/labat/apotout.dat b/src/labat/apotout.dat
new file mode 100644
index 0000000..c8b9361
--- /dev/null
+++ b/src/labat/apotout.dat
@@ -0,0 +1,402 @@
1 23 z,ion: 13. 0. jblock,nbl,c: 10 40 0.2000000
2 0. -13. 0. 1388.3896
3 0.0005 -25955.4876 -26035.9849 1388.3896
4 0.001 -12955.4904 -13002.2249 1370.4157
5 0.0015 -8622.15995 -8657.40852 1352.67242
6 0.002 -6455.49896 -6484.42383 1335.15901
7 0.0025 -5155.50461 -5180.8752 1317.87344
8 0.003 -4288.84631 -4311.74825 1300.81287
9 0.0035 -3669.807 -3690.95678 1283.97453
10 0.004 -3205.53222 -3225.34899 1267.35557
11 0.0045 -2844.43198 -2863.20362 1250.9532
12 0.005 -2555.5565 -2573.48224 1234.76462
13 0.0055 -2319.20618 -2336.43164 1218.7871
14 0.006 -2122.25227 -2138.88651 1203.01789
15 0.0065 -1955.60128 -1971.72833 1187.45432
16 0.007 -1812.7622 -1828.44808 1172.09372
17 0.0075 -1688.97061 -1704.26822 1156.93347
18 0.008 -1580.65752 -1595.60984 1141.97097
19 0.0085 -1485.0894 -1499.73187 1127.20367
20 0.009 -1400.14442 -1414.50662 1112.62903
21 0.0095 -1324.14322 -1338.25008 1098.24456
22 0.01 -1255.74651 -1269.61925 1084.04779
23 0.0105 -1193.86593 -1207.52278 1070.03628
24 0.011 -1137.61514 -1151.07185 1056.20763
25 0.0115 -1086.25784 -1099.52814 1042.55946
26 0.012 -1039.1845 -1052.28042 1029.08944
27 0.0125 -995.879101 -1008.81125 1015.79523
28 0.013 -955.908974 -968.686775 1002.67457
29 0.0135 -918.901619 -931.533454 989.725183
30 0.014 -884.541644 -897.03502 976.944851
31 0.0145 -852.553298 -864.914965 964.331372
32 0.015 -822.701413 -834.937463 951.882574
33 0.0155 -794.777386 -806.893339 939.596312
34 0.016 -768.602423 -780.603299 927.470469
35 0.0165 -744.015705 -755.906084 915.502957
36 0.017 -720.878987 -732.66306 903.691711
37 0.0175 -699.066205 -710.747819 892.034694
38 0.018 -678.468878 -690.051574 880.529897
39 0.0185 -658.986714 -670.473757 869.175334
40 0.019 -640.533471 -651.927899 857.969045
41 0.0195 -623.0283 -634.332869 846.909096
42 0.02 -606.401847 -617.619387 835.993579
43 0.021 -575.529149 -586.579343 814.58832
44 0.022 -547.476089 -558.367253 793.738484
45 0.023 -521.868786 -532.608675 773.429655
46 0.024 -498.407843 -509.003021 753.647795
47 0.025 -476.829838 -487.286223 734.37922
48 0.026 -456.92351 -467.246399 715.610606
49 0.027 -438.497498 -448.691673 697.328962
50 0.028 -421.398897 -431.468693 679.52164
51 0.029 -405.485005 -415.434375 662.176315
52 0.03 -390.642765 -400.475327 645.280982
53 0.031 -376.76332 -386.482402 628.823944
54 0.032 -363.761548 -373.37022 612.793809
55 0.033 -351.552739 -361.05385 597.179478
56 0.034 -340.071808 -349.468005 581.970143
57 0.035 -329.251666 -338.545419 567.155272
58 0.036 -319.041882 -328.235504 552.724611
59 0.037 -309.388483 -318.484145 538.668167
60 0.038 -300.251946 -309.251693 524.976213
61 0.039 -291.588234 -300.493996 511.639269
62 0.04 -283.366067 -292.17967 498.648106
63 0.041 -275.549056 -284.272233 485.993731
64 0.042 -268.112233 -276.746632 473.66739
65 0.043 -261.025184 -269.572375 461.660553
66 0.044 -254.267834 -262.729315 449.964914
67 0.045 -247.814496 -256.191702 438.572383
68 0.046 -241.648926 -249.94323 427.475082
69 0.047 -235.749227 -243.961948 416.665337
70 0.048 -230.102184 -238.23459 406.135674
71 0.049 -224.688965 -232.742278 395.878815
72 0.05 -219.498776 -227.474172 385.887672
73 0.051 -214.515292 -222.41391 376.155341
74 0.052 -209.729663 -217.552602 366.675098
75 0.053 -205.127637 -212.875962 357.440396
76 0.054 -200.701935 -208.376678 348.444857
77 0.055 -196.440033 -204.042195 339.682271
78 0.056 -192.335932 -199.866487 331.14659
79 0.057 -188.37856 -195.83845 322.831922
80 0.058 -184.562965 -191.95313 314.732531
81 0.059 -180.879305 -188.200564 306.842829
82 0.06 -177.323488 -184.577119 299.157376
83 0.062 -170.563242 -177.68364 284.378151
84 0.064 -164.243976 -171.233797 270.354108
85 0.066 -158.31648 -165.179383 257.04658
86 0.068 -152.754381 -159.49325 244.418904
87 0.07 -147.518073 -154.13582 232.436292
88 0.072 -142.587816 -149.087217 221.065756
89 0.074 -137.931267 -144.315012 210.275993
90 0.076 -133.533522 -139.804212 200.037321
91 0.078 -129.367834 -135.527992 190.321573
92 0.08 -125.422866 -131.474943 181.102036
93 0.082 -121.676257 -127.622637 172.353361
94 0.084 -118.119334 -123.962337 164.051505
95 0.086 -114.733219 -120.475109 156.173655
96 0.088 -111.511247 -117.154234 148.698169
97 0.09 -108.437347 -113.983587 141.604509
98 0.092 -105.506378 -110.957984 134.873195
99 0.094 -102.704554 -108.063593 128.485738
100 0.096 -100.027905 -105.296401 122.424596
101 0.098 -97.4645262 -102.644462 116.673124
102 0.1 -95.0113453 -100.104668 111.215528
103 0.102 -92.6580213 -97.666641 106.036817
104 0.104 -90.4021799 -95.3279715 101.122768
105 0.106 -88.2347892 -93.0795947 96.4598809
106 0.108 -86.1540174 -90.9196464 92.0353461
107 0.11 -84.151938 -88.840169 87.8370041
108 0.112 -82.2271432 -86.8397243 83.8533162
109 0.114 -80.3726458 -84.9112952 80.0733299
110 0.116 -78.5873706 -83.0537776 76.4866505
111 0.118 -76.8651328 -81.2609577 73.0834112
112 0.12 -75.2051194 -79.5319941 69.8542473
113 0.122 -73.6018352 -77.8613631 66.7902694
114 0.124 -72.0546739 -76.24843 63.8830401
115 0.126 -70.5587356 -74.6882666 61.1245496
116 0.128 -69.113578 -73.1804017 58.5071955
117 0.13 -67.7148172 -71.7204225 56.0237603
118 0.132 -66.362141 -70.307988 53.6673935
119 0.134 -65.0516147 -68.9391302 51.4315911
120 0.136 -63.7830296 -67.6136311 49.3101797
121 0.138 -62.5528436 -66.327814 47.2972981
122 0.14 -61.3609303 -65.0821349 45.387383
123 0.144 -59.0808659 -62.6978646 41.8555907
124 0.148 -56.9349658 -60.4517957 38.6756821
125 0.152 -54.9070555 -58.3291087 35.8123973
126 0.156 -52.9924951 -56.3240681 33.2339623
127 0.16 -51.178006 -54.4233072 30.9117391
128 0.164 -49.4601134 -52.6230381 28.8199127
129 0.168 -47.8277963 -50.9120235 26.9352389
130 0.172 -46.2784539 -49.287447 25.2367647
131 0.176 -44.802842 -47.7398693 23.7056094
132 0.18 -43.3990267 -46.2672108 22.3247649
133 0.184 -42.0591742 -44.8615294 21.0789087
134 0.188 -40.7818674 -43.5213485 19.954241
135 0.192 -39.5604007 -42.2399508 18.9383331
136 0.196 -38.3937632 -41.0163602 18.0199949
137 0.2 -37.2761582 -39.8448573 17.1891513
138 0.204 -36.2068987 -38.7248663 16.4367349
139 0.208 -35.1809254 -37.6514634 15.754585
140 0.212 -34.1978119 -36.6243676 15.1353604
141 0.216 -33.2531013 -35.6392628 14.572457
142 0.22 -32.3465793 -34.6960538 14.0599373
143 0.224 -31.474284 -33.7908604 13.5924632
144 0.228 -30.6361756 -32.9236715 13.165238
145 0.232 -29.8287018 -32.0908994 12.7739526
146 0.236 -29.0519663 -31.2925408 12.414738
147 0.24 -28.3027584 -30.5252037 12.0841211
148 0.244 -27.5813012 -29.7888603 11.7789869
149 0.248 -26.8846701 -29.0802754 11.4965419
150 0.252 -26.2131874 -28.3994151 11.2342835
151 0.256 -25.5641709 -27.743215 10.9899705
152 0.26 -24.938025 -27.1116894 10.7615981
153 0.264 -24.3322739 -26.501982 10.5473736
154 0.268 -23.7473903 -25.914208 10.3456962
155 0.272 -23.1810754 -25.3457431 10.1551372
156 0.276 -22.6338585 -24.7968282 9.97442364
157 0.28 -22.1035942 -24.2650724 9.802422
158 0.284 -21.5908578 -23.7508434 9.63812469
159 0.288 -21.093638 -23.251979 9.48063693
160 0.292 -20.6125475 -22.768953 9.32916572
161 0.296 -20.145693 -22.2997973 9.18300901
162 0.3 -19.6937169 -21.8454622 9.04154678
163 0.308 -18.8285251 -20.9734428 8.77058317
164 0.316 -18.0163073 -20.1522563 8.51265026
165 0.324 -17.2486506 -19.3746181 8.26496577
166 0.332 -16.5266385 -18.6409913 8.0254235
167 0.34 -15.8428052 -17.9442094 7.79244879
168 0.348 -15.1985765 -17.285773 7.56489148
169 0.356 -14.5872668 -16.6591098 7.34192906
170 0.364 -14.0105277 -16.0659685 7.12299838
171 0.372 -13.4623317 -15.5004216 6.90773143
172 0.38 -12.944469 -14.9643603 6.69591252
173 0.388 -12.4514775 -14.4524224 6.48743584
174 0.396 -11.985221 -13.9665684 6.28227942
175 0.404 -11.5407318 -13.5019216 6.08047725
176 0.412 -11.119898 -13.0604543 5.88210419
177 0.42 -10.7181896 -12.637713 5.68725782
178 0.428 -10.337483 -12.235643 5.49605039
179 0.436 -9.97363998 -11.8501679 5.30859716
180 0.444 -9.62849844 -11.4831807 5.12501283
181 0.452 -9.29827352 -11.1309458 4.94540415
182 0.46 -8.98474556 -10.7952873 4.76986906
183 0.468 -8.68445022 -10.4727802 4.59849215
184 0.476 -8.39909707 -10.1651686 4.43134544
185 0.484 -8.12551375 -9.86931144 4.26848561
186 0.492 -7.86533024 -9.58686623 4.10995565
187 0.5 -7.61564097 -9.3149522 3.95578333
188 0.508 -7.37799103 -9.05513641 3.80598319
189 0.516 -7.14971907 -8.8047773 3.66055579
190 0.524 -6.93228265 -8.56534991 3.51948982
191 0.532 -6.72324432 -8.33443262 3.38276174
192 0.54 -6.52397342 -8.11340872 3.2503379
193 0.548 -6.33223792 -7.90005883 3.12217443
194 0.556 -6.14931982 -7.6956761 2.99821919
195 0.564 -5.97317563 -7.49822714 2.8784118
196 0.572 -5.80500198 -7.30891749 2.76268542
197 0.58 -5.64292843 -7.12588467 2.65096684
198 0.588 -5.48806909 -6.95025023 2.54317799
199 0.596 -5.3387123 -6.78030731 2.43923614
200 0.604 -5.195893 -6.61710268 2.33905514
201 0.612 -5.05804527 -6.45905125 2.2425456
202 0.62 -4.92612862 -6.30722765 2.14961601
203 0.636 -4.67562195 -6.01744374 1.97412109
204 0.652 -4.44566994 -5.74890413 1.81181156
205 0.668 -4.23052624 -5.49618914 1.66191892
206 0.684 -4.03240949 -5.26136188 1.52368165
207 0.7 -3.8465426 -5.03969472 1.39634993
208 0.716 -3.67483817 -4.833094 1.27919637
209 0.732 -3.51332341 -4.63759222 1.17151799
210 0.748 -3.36363591 -4.45482501 1.07264259
211 0.764 -3.22247032 -4.28148507 0.981929034
212 0.78 -3.09122154 -4.11896256 0.898770548
213 0.796 -2.96713792 -3.96450079 0.822593918
214 0.812 -2.85140313 -3.81927694 0.752860843
215 0.828 -2.74172462 -3.6809921 0.689066436
216 0.844 -2.63910413 -3.5506409 0.630739347
217 0.86 -2.54162963 -3.42630476 0.57743993
218 0.876 -2.45014743 -3.30882321 0.528759622
219 0.892 -2.36306077 -3.19659337 0.484319004
220 0.908 -2.28108404 -3.0903235 0.443766759
221 0.924 -2.20288158 -2.98867227 0.406777764
222 0.94 -2.12905644 -2.89223684 0.373051862
223 0.956 -2.0584891 -2.79989167 0.342312061
224 0.972 -1.99168909 -2.71213938 0.314303251
225 0.988 -1.9277158 -2.62803134 0.288790558
226 1.004 -1.86700047 -2.54798889 0.2655581
227 1.02 -1.80875054 -2.47120717 0.244407506
228 1.036 -1.75333198 -2.39803675 0.225156752
229 1.052 -1.7000747 -2.32778845 0.207638859
230 1.068 -1.64929043 -2.26075065 0.191700832
231 1.084 -1.60041039 -2.19632655 0.177202523
232 1.1 -1.55370134 -2.13474992 0.164015687
233 1.116 -1.50867833 -2.07549783 0.152022997
234 1.132 -1.46557091 -2.01875707 0.141117213
235 1.148 -1.42396353 -1.96406511 0.131200335
236 1.164 -1.38405502 -1.91157044 0.122182882
237 1.18 -1.34548726 -1.86086279 0.113983169
238 1.196 -1.30843378 -1.81206267 0.106526681
239 1.212 -1.27258406 -1.76480959 0.099745456
240 1.228 -1.2380908 -1.7192104 0.0935775561
241 1.244 -1.20468294 -1.67493554 0.0879665378
242 1.26 -1.17249605 -1.63230557 0.0828609995
243 1.292 -1.1110338 -1.55045023 0.0739832945
244 1.324 -1.05378121 -1.47315545 0.0666183437
245 1.356 -0.999788814 -1.40081147 0.0604963825
246 1.388 -0.949300004 -1.33371461 0.0553943894
247 1.42 -0.901551246 -1.27197391 0.0511281129
248 1.452 -0.856765003 -1.2163633 0.0475454497
249 1.484 -0.814309323 -1.16654104 0.0445208384
250 1.516 -0.7743937 -1.12253391 0.0419507429
251 1.548 -0.736480777 -1.08320985 0.0397498527
252 1.58 -0.700771753 -1.0479237 0.0378480528
253 1.612 -0.666798697 -1.01533405 0.03618785
254 1.644 -0.634756994 -0.98491388 0.0347222995
255 1.676 -0.604231022 -0.955762397 0.0334132007
256 1.708 -0.57541142 -0.927816107 0.0322296281
257 1.74 -0.547923251 -0.900619444 0.0311466379
258 1.772 -0.521952624 -0.874381494 0.0301442262
259 1.804 -0.49715736 -0.848830643 0.029206412
260 1.836 -0.473718787 -0.824230381 0.0283205168
261 1.868 -0.451322038 -0.800341498 0.0274765291
262 1.9 -0.430143189 -0.777402298 0.0266666175
263 1.932 -0.409890891 -0.755169751 0.0258846952
264 1.964 -0.390735421 -0.733850502 0.0251260965
265 1.996 -0.372406246 -0.713201294 0.0243872797
266 2.028 -0.355067324 -0.693406724 0.0236656139
267 2.06 -0.338466953 -0.6742312 0.0229591768
268 2.092 -0.322762323 -0.655844908 0.0222666158
269 2.124 -0.307719043 -0.638024436 0.0215870105
270 2.156 -0.293487193 -0.620929444 0.0209197841
271 2.188 -0.27984847 -0.604350316 0.0202646099
272 2.22 -0.26694561 -0.588437767 0.019621356
273 2.252 -0.254575371 -0.572996059 0.0189900228
274 2.284 -0.242873011 -0.558167472 0.0183707096
275 2.316 -0.23164945 -0.543769585 0.017763573
276 2.348 -0.221032434 -0.529936372 0.0171688084
277 2.38 -0.210846222 -0.516497961 0.0165866224
278 2.412 -0.201211097 -0.503580143 0.0160172241
279 2.444 -0.19196389 -0.491024674 0.0154608071
280 2.476 -0.183217543 -0.478949667 0.0149175474
281 2.508 -0.174820728 -0.46720714 0.0143875912
282 2.54 -0.166879229 -0.4559057 0.0138710569
283 2.604 -0.151929988 -0.434222199 0.0128785532
284 2.668 -0.138560595 -0.414108452 0.0119403188
285 2.732 -0.126217715 -0.395025007 0.0110560748
286 2.796 -0.115181289 -0.377273651 0.0102250884
287 2.86 -0.104981819 -0.36039622 0.00944618503
288 2.924 -0.0958629313 -0.344645705 0.00871786277
289 2.988 -0.0874274208 -0.329632317 0.00803832713
290 3.052 -0.0798857884 -0.315571534 0.00740558938
291 3.116 -0.0729028537 -0.3021327 0.00681750058
292 3.18 -0.0666594558 -0.289499771 0.00627182705
293 3.244 -0.0608733757 -0.277394018 0.00576627626
294 3.308 -0.0556992609 -0.265973254 0.00529855068
295 3.372 -0.0508999204 -0.255004458 0.00486636454
296 3.436 -0.0466071215 -0.244623904 0.00446747976
297 3.5 -0.042621813 -0.234638428 0.00409971514
298 3.564 -0.039055943 -0.225166652 0.00376096883
299 3.628 -0.0357426604 -0.21604973 0.0034492217
300 3.692 -0.0327768615 -0.207391423 0.00316255027
301 3.756 -0.030018806 -0.199061826 0.00289912613
302 3.82 -0.027548798 -0.191151679 0.0026572223
303 3.884 -0.0252498699 -0.18355483 0.00243521024
304 3.948 -0.0231898935 -0.176350116 0.00223156185
305 4.012 -0.0212709928 -0.169450326 0.00204484511
306 4.076 -0.0195504845 -0.162923103 0.00187372338
307 4.14 -0.0179464726 -0.156695965 0.00171695032
308 4.204 -0.0165073374 -0.150825919 0.00157336764
309 4.268 -0.0151645426 -0.145251747 0.00144189977
310 4.332 -0.0139589185 -0.140020527 0.00132155074
311 4.396 -0.0128330872 -0.135079525 0.00121139894
312 4.46 -0.0118215111 -0.130466681 0.00111059354
313 4.524 -0.0108761264 -0.126135728 0.00101834962
314 4.588 -0.0100260305 -0.122116377 0.000933944425
315 4.652 -0.00923093195 -0.118367297 0.000856712853
316 4.716 -0.00851541128 -0.114910969 0.000786043851
317 4.78 -0.00784566261 -0.111709715 0.000721376309
318 4.844 -0.007242465 -0.10878006 0.000662195676
319 4.908 -0.00667742537 -0.106086191 0.0006080303
320 4.972 -0.00616812367 -0.103639571 0.000558448336
321 5.036 -0.00569068627 -0.10141813 0.000513054515
322 5.1 -0.00526000025 -0.0992762735 0.000471487394
323 5.228 -0.00447761068 -0.095782979 0.000398541493
324 5.356 -0.00383940848 -0.0932147911 0.0003372963
325 5.484 -0.00327621448 -0.0907980421 0.000285818263
326 5.612 -0.0028153837 -0.0887309954 0.000242501611
327 5.74 -0.00240764875 -0.0866198114 0.000206009491
328 5.868 -0.00207302125 -0.0842367752 0.000175230412
329 5.996 -0.00177621909 -0.0812901623 0.000149239647
330 6.124 -0.00153193652 -0.0776496372 0.000127267556
331 6.252 -0.00131476745 -0.0733064333 0.000108672511
332 6.38 -0.00113554625 -0.0684550186 9.29186434E-05
333 6.508 -0.00097587795 -0.0633628896 7.95573376E-05
334 6.636 -0.000843787789 -0.0583374804 6.82123256E-05
335 6.764 -0.00072588243 -0.0536092996 5.85675348E-05
336 6.892 -0.000628135765 -0.0493446456 5.03572882E-05
337 7.02 -0.000540739576 -0.0456136891 4.33581998E-05
338 7.148 -0.000468162817 -0.0424395841 3.73824711E-05
339 7.276 -0.000403180398 -0.039793429 3.22722304E-05
340 7.404 -0.000349150908 -0.0376341537 2.78947771E-05
341 7.532 -0.000300721511 -0.0359011349 2.41385453E-05
342 7.66 -0.000260426344 -0.0345382078 2.09097083E-05
343 7.788 -0.000224278582 -0.0334827596 1.81293111E-05
344 7.916 -0.000194196146 -0.032679244 1.57308675E-05
345 8.044 -0.000167195916 -0.032067589 1.36583436E-05
346 8.172 -0.000144732221 -0.0315908422 1.18644738E-05
347 8.3 -0.000124564766 -0.0311850752 1.03093533E-05
348 8.428 -0.000107797002 -0.0307852986 8.95926276E-06
349 8.556 -9.27422736E-05 -0.0303202886 7.78568407E-06
350 8.684 -8.02371475E-05 -0.0297221369 6.76447296E-06
351 8.812 -6.90103045E-05 -0.028929475 5.87515777E-06
352 8.94 -5.96946823E-05 -0.0279014228 5.10034163E-06
353 9.068 -5.13322329E-05 -0.026622781 4.42518973E-06
354 9.196 -4.44004582E-05 -0.0251105685 3.83699167E-06
355 9.324 -3.81784313E-05 -0.0234078245 3.32479279E-06
356 9.452 -3.30252738E-05 -0.0215763769 2.87909088E-06
357 9.58 -2.83997197E-05 -0.0196833543 2.49159314E-06
358 9.708 -2.45711067E-05 -0.0177920682 2.15502603E-06
359 9.836 -2.11340862E-05 -0.0159558646 1.86298825E-06
360 9.964 -1.82902227E-05 -0.0142116609 1.60983627E-06
361 10.092 -1.57366592E-05 -0.0125872179 1.39059377E-06
362 10.22 -1.36240196E-05 -0.0111365643 1.20087597E-06
363 10.476 -1.00360257E-05 -0.00855331294 8.95043669E-07
364 10.732 -7.57858023E-06 -0.00645001052 6.66868225E-07
365 10.988 -5.59324512E-06 -0.00488484266 4.9690287E-07
366 11.244 -4.2315225E-06 -0.0036719993 3.70398737E-07
367 11.5 -3.12926032E-06 -0.00275580821 2.76267649E-07
368 11.756 -2.37175827E-06 -0.00206442544 2.06214669E-07
369 12.012 -1.75734979E-06 -0.00154547605 1.54057202E-07
370 12.268 -1.33421838E-06 -0.0011567623 1.15197825E-07
371 12.524 -9.90339825E-07 -0.000865979602 8.62225224E-08
372 12.78 -7.53019451E-07 -0.000648621482 6.4597635E-08
373 13.036 -5.59789793E-07 -0.000486134457 4.8442975E-08
374 13.292 -4.26172329E-07 -0.000364656213 3.63628311E-08
375 13.548 -3.17191632E-07 -0.000273771529 2.73205026E-08
376 13.804 -2.41696471E-07 -0.00020574002 2.05453389E-08
377 14.06 -1.80025182E-07 -0.000154762947 1.54639331E-08
378 14.316 -1.37236292E-07 -0.000116537277 1.16492103E-08
379 14.572 -1.02234269E-07 -8.78401813E-05 8.78275108E-09
380 14.828 -7.7918381E-08 -6.62792088E-05 6.62689483E-09
381 15.084 -5.80044889E-08 -5.00604659E-05 5.004068E-09
382 15.34 -4.41583574E-08 -3.78504749E-05 3.78145267E-09
383 15.596 -3.28088435E-08 -2.86475556E-05 2.85960361E-09
384 15.852 -2.49152294E-08 -2.17057681E-05 2.16398781E-09
385 16.108 -1.84417362E-08 -1.64635883E-05 1.63868893E-09
386 16.364 -1.3942026E-08 -1.25020194E-05 1.24171762E-09
387 16.62 -1.02521781E-08 -9.50495421E-06 9.41513835E-10
388 16.876 -7.69243803E-09 -7.23604132E-06 7.14335481E-10
389 17.132 -5.59553062E-09 -5.51657994E-06 5.42306598E-10
390 17.388 -4.1470892E-09 -4.2126917E-06 4.11956927E-10
391 17.644 -2.96357552E-09 -3.22294475E-06 3.13128071E-10
392 17.9 -2.15283223E-09 -2.47120067E-06 2.381534E-10
393 18.156 -1.4938624E-09 -1.89967742E-06 1.81242601E-10
394 18.412 -1.04946643E-09 -1.46487347E-06 1.38019384E-10
395 18.668 -6.91996791E-10 -1.13388331E-06 1.05173916E-10
396 18.924 -4.58124333E-10 -8.81381236E-07 8.02012948E-11
397 19.18 -2.73940422E-10 -6.89699784E-07 6.12045912E-11
398 19.436 -1.6092993E-10 -5.40597174E-07 4.67464071E-11
399 19.692 -7.61894269E-11 -4.34889002E-07 3.57369105E-11
400 19.948 -3.23618296E-11 -3.31990888E-07 2.7349321E-11
401 20.204 -4.47031275E-12 -3.06634084E-07 2.09560724E-11
402 20.46 0. -2.77585617E-07 1.60805574E-11
diff --git a/src/labat/aprtout.dat b/src/labat/aprtout.dat
new file mode 100644
index 0000000..e55c256
--- /dev/null
+++ b/src/labat/aprtout.dat
@@ -0,0 +1,1175 @@
1
2 atom number: 13. ionicity: 0.
3
4 perdew - wang xc
5
6 hermann-skillmann mesh
7 blocks, nbl, c: 10, 40, 0.2000000
8 first interval, last interval, final r: 0.000500, 0.256000, 20.460000
9
10 energy eigenvalue threshold, screening parameter, feedback: 0.000010, 0.005000, 0.500
11
12
13 initial bound state configuration
14 nlm energy occup. val.el. d-band el.
15 100 -0.8450E+02 1.00 1 0
16 200 -0.1625E+02 1.00 1 0
17 210 -0.5336E+01 3.00 1 0
18 300 -0.7812E+00 1.00 1 0
19 310 -0.2312E+00 1.00 1 0
20 100 -0.8450E+02 1.00 1 0
21 200 -0.1625E+02 1.00 1 0
22 210 -0.5336E+01 3.00 1 0
23 300 -0.7812E+00 1.00 1 0
24 310 -0.2312E+00 0.00 1 0
25
26 number of valence electrons: 13.0
27
28 initial potentials
29
30
31
32
33 ********************* iteration: 1 ***********************
34
35 l = 0, 3 bound states
36 l = 1, 1 bound states
37 l = 0, 3 bound states
38 l = 1, 1 bound states
39
40
41 bound states
42
43 100 energy: -51.97833 iteration loops: 7
44 200 energy: -3.47892 iteration loops: 10
45 300 energy: -0.08955 iteration loops: 15
46 210 energy: -2.09653 iteration loops: 13
47 100 energy: -51.97833 iteration loops: 7
48 200 energy: -3.47892 iteration loops: 10
49 300 energy: -0.08955 iteration loops: 15
50 210 energy: -2.09653 iteration loops: 13
51
52 integr charges: total 12.0000000 valence: 12.0000000 0.0000000
53 induced moment: 0.00000
54
55 energy terms
56 energy eigenvalue sum: -0.123673E+03
57 kin: 0.175039E+03 0.175039E+03 coul: -0.451615E+03 exc: -0.175124E+02
58
59 total energy: -0.2427229E+03
60
61 charge and spin density profiles
62
63 valence energy: -0.2423878E+03
640
65 potentials vs. distance after 1 iterations
66
67 0.00050 -0.25944E+05 -0.81015E+02 -0.81015E+02 -0.25978E+05 -0.25978E+05
68 0.00100 -0.12948E+05 -0.46840E+02 -0.46840E+02 -0.12967E+05 -0.12967E+05
69 0.00150 -0.86168E+04 -0.35293E+02 -0.35293E+02 -0.86307E+04 -0.86307E+04
70 0.00200 -0.64512E+04 -0.28887E+02 -0.28887E+02 -0.64625E+04 -0.64625E+04
71 0.00250 -0.51519E+04 -0.25299E+02 -0.25299E+02 -0.51618E+04 -0.51618E+04
72 0.00300 -0.42858E+04 -0.22804E+02 -0.22804E+02 -0.42947E+04 -0.42947E+04
73 0.00350 -0.36672E+04 -0.21035E+02 -0.21035E+02 -0.36755E+04 -0.36755E+04
74 0.00400 -0.32033E+04 -0.19689E+02 -0.19689E+02 -0.32111E+04 -0.32111E+04
75 0.00450 -0.28425E+04 -0.18635E+02 -0.18635E+02 -0.28499E+04 -0.28499E+04
76 0.00500 -0.25539E+04 -0.17782E+02 -0.17782E+02 -0.25610E+04 -0.25610E+04
77 0.00550 -0.23178E+04 -0.17076E+02 -0.17076E+02 -0.23246E+04 -0.23246E+04
78 0.00600 -0.21210E+04 -0.16480E+02 -0.16480E+02 -0.21277E+04 -0.21277E+04
79 0.00650 -0.19546E+04 -0.15970E+02 -0.15970E+02 -0.19611E+04 -0.19611E+04
80 0.00700 -0.18119E+04 -0.15526E+02 -0.15526E+02 -0.18183E+04 -0.18183E+04
81 0.00750 -0.16883E+04 -0.15135E+02 -0.15135E+02 -0.16945E+04 -0.16945E+04
82 0.00800 -0.15801E+04 -0.14788E+02 -0.14788E+02 -0.15862E+04 -0.15862E+04
83 0.00850 -0.14847E+04 -0.14477E+02 -0.14477E+02 -0.14907E+04 -0.14907E+04
84 0.00900 -0.13998E+04 -0.14196E+02 -0.14196E+02 -0.14058E+04 -0.14058E+04
85 0.00950 -0.13239E+04 -0.13940E+02 -0.13940E+02 -0.13298E+04 -0.13298E+04
86 0.01000 -0.12556E+04 -0.13705E+02 -0.13705E+02 -0.12615E+04 -0.12615E+04
87 0.01050 -0.11939E+04 -0.13489E+02 -0.13489E+02 -0.11996E+04 -0.11996E+04
88 0.01100 -0.11377E+04 -0.13289E+02 -0.13289E+02 -0.11434E+04 -0.11434E+04
89 0.01150 -0.10864E+04 -0.13102E+02 -0.13102E+02 -0.10921E+04 -0.10921E+04
90 0.01200 -0.10394E+04 -0.12928E+02 -0.12928E+02 -0.10451E+04 -0.10451E+04
91 0.01250 -0.99622E+03 -0.12764E+02 -0.12764E+02 -0.10018E+04 -0.10018E+04
92 0.01300 -0.95632E+03 -0.12610E+02 -0.12610E+02 -0.96186E+03 -0.96186E+03
93 0.01350 -0.91938E+03 -0.12465E+02 -0.12465E+02 -0.92489E+03 -0.92489E+03
94 0.01400 -0.88509E+03 -0.12327E+02 -0.12327E+02 -0.89056E+03 -0.89056E+03
95 0.01450 -0.85317E+03 -0.12195E+02 -0.12195E+02 -0.85860E+03 -0.85860E+03
96 0.01500 -0.82337E+03 -0.12070E+02 -0.12070E+02 -0.82878E+03 -0.82878E+03
97 0.01550 -0.79551E+03 -0.11951E+02 -0.11951E+02 -0.80089E+03 -0.80089E+03
98 0.01600 -0.76939E+03 -0.11836E+02 -0.11836E+02 -0.77474E+03 -0.77474E+03
99 0.01650 -0.74485E+03 -0.11727E+02 -0.11727E+02 -0.75018E+03 -0.75018E+03
100 0.01700 -0.72177E+03 -0.11621E+02 -0.11621E+02 -0.72706E+03 -0.72706E+03
101 0.01750 -0.70000E+03 -0.11519E+02 -0.11519E+02 -0.70527E+03 -0.70527E+03
102 0.01800 -0.67945E+03 -0.11421E+02 -0.11421E+02 -0.68470E+03 -0.68470E+03
103 0.01850 -0.66002E+03 -0.11327E+02 -0.11327E+02 -0.66524E+03 -0.66524E+03
104 0.01900 -0.64161E+03 -0.11235E+02 -0.11235E+02 -0.64680E+03 -0.64680E+03
105 0.01950 -0.62414E+03 -0.11146E+02 -0.11146E+02 -0.62932E+03 -0.62932E+03
106 0.02000 -0.60756E+03 -0.11060E+02 -0.11060E+02 -0.61271E+03 -0.61271E+03
107 0.02100 -0.57676E+03 -0.10894E+02 -0.10894E+02 -0.58187E+03 -0.58187E+03
108 0.02200 -0.54877E+03 -0.10737E+02 -0.10737E+02 -0.55384E+03 -0.55384E+03
109 0.02300 -0.52323E+03 -0.10588E+02 -0.10588E+02 -0.52826E+03 -0.52826E+03
110 0.02400 -0.49983E+03 -0.10445E+02 -0.10445E+02 -0.50482E+03 -0.50482E+03
111 0.02500 -0.47831E+03 -0.10308E+02 -0.10308E+02 -0.48326E+03 -0.48326E+03
112 0.02600 -0.45845E+03 -0.10177E+02 -0.10177E+02 -0.46337E+03 -0.46337E+03
113 0.02700 -0.44008E+03 -0.10050E+02 -0.10050E+02 -0.44495E+03 -0.44495E+03
114 0.02800 -0.42302E+03 -0.99279E+01 -0.99279E+01 -0.42786E+03 -0.42786E+03
115 0.02900 -0.40715E+03 -0.98095E+01 -0.98095E+01 -0.41195E+03 -0.41195E+03
116 0.03000 -0.39234E+03 -0.96948E+01 -0.96948E+01 -0.39711E+03 -0.39711E+03
117 0.03100 -0.37850E+03 -0.95835E+01 -0.95835E+01 -0.38323E+03 -0.38323E+03
118 0.03200 -0.36553E+03 -0.94752E+01 -0.94752E+01 -0.37023E+03 -0.37023E+03
119 0.03300 -0.35335E+03 -0.93697E+01 -0.93697E+01 -0.35801E+03 -0.35801E+03
120 0.03400 -0.34190E+03 -0.92669E+01 -0.92669E+01 -0.34653E+03 -0.34653E+03
121 0.03500 -0.33111E+03 -0.91665E+01 -0.91665E+01 -0.33570E+03 -0.33570E+03
122 0.03600 -0.32092E+03 -0.90685E+01 -0.90685E+01 -0.32548E+03 -0.32548E+03
123 0.03700 -0.31129E+03 -0.89726E+01 -0.89726E+01 -0.31581E+03 -0.31581E+03
124 0.03800 -0.30217E+03 -0.88787E+01 -0.88787E+01 -0.30666E+03 -0.30666E+03
125 0.03900 -0.29353E+03 -0.87868E+01 -0.87868E+01 -0.29798E+03 -0.29798E+03
126 0.04000 -0.28532E+03 -0.86967E+01 -0.86967E+01 -0.28974E+03 -0.28974E+03
127 0.04100 -0.27752E+03 -0.86083E+01 -0.86083E+01 -0.28191E+03 -0.28191E+03
128 0.04200 -0.27010E+03 -0.85215E+01 -0.85215E+01 -0.27445E+03 -0.27445E+03
129 0.04300 -0.26302E+03 -0.84363E+01 -0.84363E+01 -0.26734E+03 -0.26734E+03
130 0.04400 -0.25627E+03 -0.83525E+01 -0.83525E+01 -0.26056E+03 -0.26056E+03
131 0.04500 -0.24983E+03 -0.82702E+01 -0.82702E+01 -0.25408E+03 -0.25408E+03
132 0.04600 -0.24367E+03 -0.81892E+01 -0.81892E+01 -0.24789E+03 -0.24789E+03
133 0.04700 -0.23778E+03 -0.81096E+01 -0.81096E+01 -0.24197E+03 -0.24197E+03
134 0.04800 -0.23214E+03 -0.80312E+01 -0.80312E+01 -0.23629E+03 -0.23629E+03
135 0.04900 -0.22673E+03 -0.79540E+01 -0.79540E+01 -0.23085E+03 -0.23085E+03
136 0.05000 -0.22155E+03 -0.78779E+01 -0.78779E+01 -0.22563E+03 -0.22563E+03
137 0.05100 -0.21657E+03 -0.78030E+01 -0.78030E+01 -0.22062E+03 -0.22062E+03
138 0.05200 -0.21179E+03 -0.77291E+01 -0.77291E+01 -0.21581E+03 -0.21581E+03
139 0.05300 -0.20719E+03 -0.76563E+01 -0.76563E+01 -0.21117E+03 -0.21117E+03
140 0.05400 -0.20276E+03 -0.75845E+01 -0.75845E+01 -0.20672E+03 -0.20672E+03
141 0.05500 -0.19850E+03 -0.75137E+01 -0.75137E+01 -0.20242E+03 -0.20242E+03
142 0.05600 -0.19440E+03 -0.74438E+01 -0.74438E+01 -0.19829E+03 -0.19829E+03
143 0.05700 -0.19044E+03 -0.73749E+01 -0.73749E+01 -0.19430E+03 -0.19430E+03
144 0.05800 -0.18662E+03 -0.73068E+01 -0.73068E+01 -0.19045E+03 -0.19045E+03
145 0.05900 -0.18294E+03 -0.72396E+01 -0.72396E+01 -0.18673E+03 -0.18673E+03
146 0.06000 -0.17938E+03 -0.71736E+01 -0.71736E+01 -0.18314E+03 -0.18314E+03
147 0.06200 -0.17261E+03 -0.70436E+01 -0.70436E+01 -0.17631E+03 -0.17631E+03
148 0.06400 -0.16628E+03 -0.69162E+01 -0.69162E+01 -0.16992E+03 -0.16992E+03
149 0.06600 -0.16035E+03 -0.67924E+01 -0.67924E+01 -0.16392E+03 -0.16392E+03
150 0.06800 -0.15477E+03 -0.66713E+01 -0.66713E+01 -0.15828E+03 -0.15828E+03
151 0.07000 -0.14952E+03 -0.65531E+01 -0.65531E+01 -0.15298E+03 -0.15298E+03
152 0.07200 -0.14458E+03 -0.64375E+01 -0.64375E+01 -0.14797E+03 -0.14797E+03
153 0.07400 -0.13991E+03 -0.63245E+01 -0.63245E+01 -0.14324E+03 -0.14324E+03
154 0.07600 -0.13549E+03 -0.62141E+01 -0.62141E+01 -0.13877E+03 -0.13877E+03
155 0.07800 -0.13131E+03 -0.61061E+01 -0.61061E+01 -0.13453E+03 -0.13453E+03
156 0.08000 -0.12735E+03 -0.60004E+01 -0.60004E+01 -0.13051E+03 -0.13051E+03
157 0.08200 -0.12359E+03 -0.58971E+01 -0.58971E+01 -0.12669E+03 -0.12669E+03
158 0.08400 -0.12001E+03 -0.57959E+01 -0.57959E+01 -0.12306E+03 -0.12306E+03
159 0.08600 -0.11661E+03 -0.56970E+01 -0.56970E+01 -0.11960E+03 -0.11960E+03
160 0.08800 -0.11337E+03 -0.56001E+01 -0.56001E+01 -0.11631E+03 -0.11631E+03
161 0.09000 -0.11028E+03 -0.55053E+01 -0.55053E+01 -0.11316E+03 -0.11316E+03
162 0.09200 -0.10733E+03 -0.54126E+01 -0.54126E+01 -0.11016E+03 -0.11016E+03
163 0.09400 -0.10451E+03 -0.53218E+01 -0.53218E+01 -0.10729E+03 -0.10729E+03
164 0.09600 -0.10181E+03 -0.52330E+01 -0.52330E+01 -0.10455E+03 -0.10455E+03
165 0.09800 -0.99229E+02 -0.51460E+01 -0.51460E+01 -0.10192E+03 -0.10192E+03
166 0.10000 -0.96757E+02 -0.50609E+01 -0.50609E+01 -0.99396E+02 -0.99396E+02
167 0.10200 -0.94386E+02 -0.49776E+01 -0.49776E+01 -0.96978E+02 -0.96978E+02
168 0.10400 -0.92112E+02 -0.48961E+01 -0.48961E+01 -0.94657E+02 -0.94657E+02
169 0.10600 -0.89927E+02 -0.48164E+01 -0.48164E+01 -0.92427E+02 -0.92427E+02
170 0.10800 -0.87828E+02 -0.47384E+01 -0.47384E+01 -0.90283E+02 -0.90283E+02
171 0.11000 -0.85809E+02 -0.46621E+01 -0.46621E+01 -0.88221E+02 -0.88221E+02
172 0.11200 -0.83867E+02 -0.45874E+01 -0.45874E+01 -0.86236E+02 -0.86236E+02
173 0.11400 -0.81996E+02 -0.45144E+01 -0.45144E+01 -0.84324E+02 -0.84324E+02
174 0.11600 -0.80194E+02 -0.44430E+01 -0.44430E+01 -0.82481E+02 -0.82481E+02
175 0.11800 -0.78456E+02 -0.43732E+01 -0.43732E+01 -0.80703E+02 -0.80703E+02
176 0.12000 -0.76780E+02 -0.43049E+01 -0.43049E+01 -0.78987E+02 -0.78987E+02
177 0.12200 -0.75162E+02 -0.42382E+01 -0.42382E+01 -0.77331E+02 -0.77331E+02
178 0.12400 -0.73600E+02 -0.41730E+01 -0.41730E+01 -0.75731E+02 -0.75731E+02
179 0.12600 -0.72089E+02 -0.41092E+01 -0.41092E+01 -0.74185E+02 -0.74185E+02
180 0.12800 -0.70630E+02 -0.40469E+01 -0.40469E+01 -0.72689E+02 -0.72689E+02
181 0.13000 -0.69217E+02 -0.39861E+01 -0.39861E+01 -0.71242E+02 -0.71242E+02
182 0.13200 -0.67851E+02 -0.39266E+01 -0.39266E+01 -0.69842E+02 -0.69842E+02
183 0.13400 -0.66528E+02 -0.38685E+01 -0.38685E+01 -0.68486E+02 -0.68486E+02
184 0.13600 -0.65246E+02 -0.38118E+01 -0.38118E+01 -0.67172E+02 -0.67172E+02
185 0.13800 -0.64004E+02 -0.37563E+01 -0.37563E+01 -0.65898E+02 -0.65898E+02
186 0.14000 -0.62800E+02 -0.37027E+01 -0.37027E+01 -0.64664E+02 -0.64664E+02
187 0.14400 -0.60498E+02 -0.35986E+01 -0.35986E+01 -0.62303E+02 -0.62303E+02
188 0.14800 -0.58330E+02 -0.34985E+01 -0.34985E+01 -0.60079E+02 -0.60079E+02
189 0.15200 -0.56283E+02 -0.34037E+01 -0.34037E+01 -0.57980E+02 -0.57980E+02
190 0.15600 -0.54350E+02 -0.33131E+01 -0.33131E+01 -0.55996E+02 -0.55996E+02
191 0.16000 -0.52519E+02 -0.32267E+01 -0.32267E+01 -0.54118E+02 -0.54118E+02
192 0.16400 -0.50786E+02 -0.31442E+01 -0.31442E+01 -0.52339E+02 -0.52339E+02
193 0.16800 -0.49140E+02 -0.30654E+01 -0.30654E+01 -0.50651E+02 -0.50651E+02
194 0.17200 -0.47577E+02 -0.29900E+01 -0.29900E+01 -0.49048E+02 -0.49048E+02
195 0.17600 -0.46090E+02 -0.29178E+01 -0.29178E+01 -0.47523E+02 -0.47523E+02
196 0.18000 -0.44676E+02 -0.28487E+01 -0.28487E+01 -0.46072E+02 -0.46072E+02
197 0.18400 -0.43327E+02 -0.27823E+01 -0.27823E+01 -0.44689E+02 -0.44689E+02
198 0.18800 -0.42041E+02 -0.27188E+01 -0.27188E+01 -0.43370E+02 -0.43370E+02
199 0.19200 -0.40812E+02 -0.26578E+01 -0.26578E+01 -0.42111E+02 -0.42111E+02
200 0.19600 -0.39638E+02 -0.25995E+01 -0.25995E+01 -0.40908E+02 -0.40908E+02
201 0.20000 -0.38515E+02 -0.25437E+01 -0.25437E+01 -0.39758E+02 -0.39758E+02
202 0.20400 -0.37441E+02 -0.24906E+01 -0.24906E+01 -0.38657E+02 -0.38657E+02
203 0.20800 -0.36411E+02 -0.24402E+01 -0.24402E+01 -0.37603E+02 -0.37603E+02
204 0.21200 -0.35424E+02 -0.23927E+01 -0.23927E+01 -0.36594E+02 -0.36594E+02
205 0.21600 -0.34476E+02 -0.23481E+01 -0.23481E+01 -0.35626E+02 -0.35626E+02
206 0.22000 -0.33567E+02 -0.23066E+01 -0.23066E+01 -0.34697E+02 -0.34697E+02
207 0.22400 -0.32693E+02 -0.22684E+01 -0.22684E+01 -0.33807E+02 -0.33807E+02
208 0.22800 -0.31853E+02 -0.22336E+01 -0.22336E+01 -0.32952E+02 -0.32952E+02
209 0.23200 -0.31044E+02 -0.22023E+01 -0.22023E+01 -0.32130E+02 -0.32130E+02
210 0.23600 -0.30267E+02 -0.21745E+01 -0.21745E+01 -0.31341E+02 -0.31341E+02
211 0.24000 -0.29517E+02 -0.21503E+01 -0.21503E+01 -0.30583E+02 -0.30583E+02
212 0.24400 -0.28795E+02 -0.21295E+01 -0.21295E+01 -0.29853E+02 -0.29853E+02
213 0.24800 -0.28099E+02 -0.21120E+01 -0.21120E+01 -0.29151E+02 -0.29151E+02
214 0.25200 -0.27427E+02 -0.20977E+01 -0.20977E+01 -0.28476E+02 -0.28476E+02
215 0.25600 -0.26779E+02 -0.20862E+01 -0.20862E+01 -0.27825E+02 -0.27825E+02
216 0.26000 -0.26153E+02 -0.20772E+01 -0.20772E+01 -0.27199E+02 -0.27199E+02
217 0.26400 -0.25548E+02 -0.20703E+01 -0.20703E+01 -0.26594E+02 -0.26594E+02
218 0.26800 -0.24964E+02 -0.20653E+01 -0.20653E+01 -0.26011E+02 -0.26011E+02
219 0.27200 -0.24399E+02 -0.20618E+01 -0.20618E+01 -0.25448E+02 -0.25448E+02
220 0.27600 -0.23853E+02 -0.20594E+01 -0.20594E+01 -0.24904E+02 -0.24904E+02
221 0.28000 -0.23323E+02 -0.20578E+01 -0.20578E+01 -0.24377E+02 -0.24377E+02
222 0.28400 -0.22812E+02 -0.20568E+01 -0.20568E+01 -0.23869E+02 -0.23869E+02
223 0.28800 -0.22316E+02 -0.20560E+01 -0.20560E+01 -0.23376E+02 -0.23376E+02
224 0.29200 -0.21835E+02 -0.20553E+01 -0.20553E+01 -0.22899E+02 -0.22899E+02
225 0.29600 -0.21369E+02 -0.20546E+01 -0.20546E+01 -0.22437E+02 -0.22437E+02
226 0.30000 -0.20918E+02 -0.20540E+01 -0.20540E+01 -0.21989E+02 -0.21989E+02
227 0.30800 -0.20055E+02 -0.20510E+01 -0.20510E+01 -0.21132E+02 -0.21132E+02
228 0.31600 -0.19244E+02 -0.20458E+01 -0.20458E+01 -0.20324E+02 -0.20324E+02
229 0.32400 -0.18477E+02 -0.20397E+01 -0.20397E+01 -0.19562E+02 -0.19562E+02
230 0.33200 -0.17755E+02 -0.20319E+01 -0.20319E+01 -0.18842E+02 -0.18842E+02
231 0.34000 -0.17071E+02 -0.20226E+01 -0.20226E+01 -0.18161E+02 -0.18161E+02
232 0.34800 -0.16426E+02 -0.20120E+01 -0.20120E+01 -0.17515E+02 -0.17515E+02
233 0.35600 -0.15813E+02 -0.20003E+01 -0.20003E+01 -0.16903E+02 -0.16903E+02
234 0.36400 -0.15234E+02 -0.19875E+01 -0.19875E+01 -0.16323E+02 -0.16323E+02
235 0.37200 -0.14684E+02 -0.19737E+01 -0.19737E+01 -0.15771E+02 -0.15771E+02
236 0.38000 -0.14162E+02 -0.19590E+01 -0.19590E+01 -0.15246E+02 -0.15246E+02
237 0.38800 -0.13666E+02 -0.19435E+01 -0.19435E+01 -0.14747E+02 -0.14747E+02
238 0.39600 -0.13194E+02 -0.19273E+01 -0.19273E+01 -0.14271E+02 -0.14271E+02
239 0.40400 -0.12745E+02 -0.19104E+01 -0.19104E+01 -0.13817E+02 -0.13817E+02
240 0.41200 -0.12318E+02 -0.18930E+01 -0.18930E+01 -0.13385E+02 -0.13385E+02
241 0.42000 -0.11911E+02 -0.18750E+01 -0.18750E+01 -0.12971E+02 -0.12971E+02
242 0.42800 -0.11523E+02 -0.18567E+01 -0.18567E+01 -0.12576E+02 -0.12576E+02
243 0.43600 -0.11152E+02 -0.18379E+01 -0.18379E+01 -0.12199E+02 -0.12199E+02
244 0.44400 -0.10799E+02 -0.18189E+01 -0.18189E+01 -0.11838E+02 -0.11838E+02
245 0.45200 -0.10460E+02 -0.17996E+01 -0.17996E+01 -0.11492E+02 -0.11492E+02
246 0.46000 -0.10138E+02 -0.17800E+01 -0.17800E+01 -0.11161E+02 -0.11161E+02
247 0.46800 -0.98287E+01 -0.17604E+01 -0.17604E+01 -0.10843E+02 -0.10843E+02
248 0.47600 -0.95335E+01 -0.17406E+01 -0.17406E+01 -0.10538E+02 -0.10538E+02
249 0.48400 -0.92504E+01 -0.17207E+01 -0.17207E+01 -0.10246E+02 -0.10246E+02
250 0.49200 -0.89798E+01 -0.17007E+01 -0.17007E+01 -0.99654E+01 -0.99654E+01
251 0.50000 -0.87199E+01 -0.16807E+01 -0.16807E+01 -0.96956E+01 -0.96956E+01
252 0.50800 -0.84713E+01 -0.16607E+01 -0.16607E+01 -0.94366E+01 -0.94366E+01
253 0.51600 -0.82323E+01 -0.16407E+01 -0.16407E+01 -0.91873E+01 -0.91873E+01
254 0.52400 -0.80034E+01 -0.16207E+01 -0.16207E+01 -0.89476E+01 -0.89476E+01
255 0.53200 -0.77833E+01 -0.16008E+01 -0.16008E+01 -0.87167E+01 -0.87167E+01
256 0.54000 -0.75722E+01 -0.15809E+01 -0.15809E+01 -0.84945E+01 -0.84945E+01
257 0.54800 -0.73690E+01 -0.15611E+01 -0.15611E+01 -0.82803E+01 -0.82803E+01
258 0.55600 -0.71741E+01 -0.15414E+01 -0.15414E+01 -0.80739E+01 -0.80739E+01
259 0.56400 -0.69862E+01 -0.15218E+01 -0.15218E+01 -0.78748E+01 -0.78748E+01
260 0.57200 -0.68059E+01 -0.15023E+01 -0.15023E+01 -0.76828E+01 -0.76828E+01
261 0.58000 -0.66319E+01 -0.14829E+01 -0.14829E+01 -0.74974E+01 -0.74974E+01
262 0.58800 -0.64648E+01 -0.14637E+01 -0.14637E+01 -0.73186E+01 -0.73186E+01
263 0.59600 -0.63034E+01 -0.14445E+01 -0.14445E+01 -0.71457E+01 -0.71457E+01
264 0.60400 -0.61483E+01 -0.14256E+01 -0.14256E+01 -0.69788E+01 -0.69788E+01
265 0.61200 -0.59985E+01 -0.14067E+01 -0.14067E+01 -0.68172E+01 -0.68172E+01
266 0.62000 -0.58543E+01 -0.13881E+01 -0.13881E+01 -0.66613E+01 -0.66613E+01
267 0.63600 -0.55801E+01 -0.13513E+01 -0.13513E+01 -0.63639E+01 -0.63639E+01
268 0.65200 -0.53257E+01 -0.13151E+01 -0.13151E+01 -0.60858E+01 -0.60858E+01
269 0.66800 -0.50874E+01 -0.12797E+01 -0.12797E+01 -0.58244E+01 -0.58244E+01
270 0.68400 -0.48655E+01 -0.12449E+01 -0.12449E+01 -0.55793E+01 -0.55793E+01
271 0.70000 -0.46572E+01 -0.12109E+01 -0.12109E+01 -0.53483E+01 -0.53483E+01
272 0.71600 -0.44628E+01 -0.11777E+01 -0.11777E+01 -0.51311E+01 -0.51311E+01
273 0.73200 -0.42798E+01 -0.11452E+01 -0.11452E+01 -0.49260E+01 -0.49260E+01
274 0.74800 -0.41085E+01 -0.11134E+01 -0.11134E+01 -0.47328E+01 -0.47328E+01
275 0.76400 -0.39469E+01 -0.10825E+01 -0.10825E+01 -0.45499E+01 -0.45499E+01
276 0.78000 -0.37954E+01 -0.10523E+01 -0.10523E+01 -0.43772E+01 -0.43772E+01
277 0.79600 -0.36521E+01 -0.10229E+01 -0.10229E+01 -0.42135E+01 -0.42135E+01
278 0.81200 -0.35174E+01 -0.99421E+00 -0.99421E+00 -0.40585E+01 -0.40585E+01
279 0.82800 -0.33897E+01 -0.96629E+00 -0.96629E+00 -0.39114E+01 -0.39114E+01
280 0.84400 -0.32694E+01 -0.93913E+00 -0.93913E+00 -0.37718E+01 -0.37718E+01
281 0.86000 -0.31553E+01 -0.91271E+00 -0.91271E+00 -0.36391E+01 -0.36391E+01
282 0.87600 -0.30474E+01 -0.88702E+00 -0.88702E+00 -0.35130E+01 -0.35130E+01
283 0.89200 -0.29449E+01 -0.86206E+00 -0.86206E+00 -0.33929E+01 -0.33929E+01
284 0.90800 -0.28478E+01 -0.83782E+00 -0.83782E+00 -0.32786E+01 -0.32786E+01
285 0.92400 -0.27554E+01 -0.81428E+00 -0.81428E+00 -0.31696E+01 -0.31696E+01
286 0.94000 -0.26677E+01 -0.79146E+00 -0.79146E+00 -0.30658E+01 -0.30658E+01
287 0.95600 -0.25840E+01 -0.76932E+00 -0.76932E+00 -0.29666E+01 -0.29666E+01
288 0.97200 -0.25045E+01 -0.74788E+00 -0.74788E+00 -0.28719E+01 -0.28719E+01
289 0.98800 -0.24286E+01 -0.72712E+00 -0.72712E+00 -0.27814E+01 -0.27814E+01
290 1.00400 -0.23563E+01 -0.70703E+00 -0.70703E+00 -0.26949E+01 -0.26949E+01
291 1.02000 -0.22870E+01 -0.68762E+00 -0.68762E+00 -0.26122E+01 -0.26122E+01
292 1.03600 -0.22211E+01 -0.66888E+00 -0.66888E+00 -0.25330E+01 -0.25330E+01
293 1.05200 -0.21578E+01 -0.65080E+00 -0.65080E+00 -0.24572E+01 -0.24572E+01
294 1.06800 -0.20974E+01 -0.63338E+00 -0.63338E+00 -0.23846E+01 -0.23846E+01
295 1.08400 -0.20394E+01 -0.61661E+00 -0.61661E+00 -0.23150E+01 -0.23150E+01
296 1.10000 -0.19840E+01 -0.60048E+00 -0.60048E+00 -0.22483E+01 -0.22483E+01
297 1.11600 -0.19307E+01 -0.58499E+00 -0.58499E+00 -0.21843E+01 -0.21843E+01
298 1.13200 -0.18797E+01 -0.57014E+00 -0.57014E+00 -0.21230E+01 -0.21230E+01
299 1.14800 -0.18306E+01 -0.55590E+00 -0.55590E+00 -0.20641E+01 -0.20641E+01
300 1.16400 -0.17835E+01 -0.54226E+00 -0.54226E+00 -0.20076E+01 -0.20076E+01
301 1.18000 -0.17381E+01 -0.52922E+00 -0.52922E+00 -0.19532E+01 -0.19532E+01
302 1.19600 -0.16946E+01 -0.51674E+00 -0.51674E+00 -0.19011E+01 -0.19011E+01
303 1.21200 -0.16526E+01 -0.50481E+00 -0.50481E+00 -0.18509E+01 -0.18509E+01
304 1.22800 -0.16122E+01 -0.49341E+00 -0.49341E+00 -0.18027E+01 -0.18027E+01
305 1.24400 -0.15732E+01 -0.48250E+00 -0.48250E+00 -0.17564E+01 -0.17564E+01
306 1.26000 -0.15356E+01 -0.47209E+00 -0.47209E+00 -0.17117E+01 -0.17117E+01
307 1.29200 -0.14644E+01 -0.45255E+00 -0.45255E+00 -0.16273E+01 -0.16273E+01
308 1.32400 -0.13981E+01 -0.43437E+00 -0.43437E+00 -0.15489E+01 -0.15489E+01
309 1.35600 -0.13360E+01 -0.41732E+00 -0.41732E+00 -0.14757E+01 -0.14757E+01
310 1.38800 -0.12781E+01 -0.40112E+00 -0.40112E+00 -0.14073E+01 -0.14073E+01
311 1.42000 -0.12237E+01 -0.38551E+00 -0.38551E+00 -0.13431E+01 -0.13431E+01
312 1.45200 -0.11728E+01 -0.37036E+00 -0.37036E+00 -0.12828E+01 -0.12828E+01
313 1.48400 -0.11248E+01 -0.35566E+00 -0.35566E+00 -0.12260E+01 -0.12260E+01
314 1.51600 -0.10797E+01 -0.34154E+00 -0.34154E+00 -0.11726E+01 -0.11726E+01
315 1.54800 -0.10372E+01 -0.32826E+00 -0.32826E+00 -0.11224E+01 -0.11224E+01
316 1.58000 -0.99714E+00 -0.31620E+00 -0.31620E+00 -0.10754E+01 -0.10754E+01
317 1.61200 -0.95925E+00 -0.30571E+00 -0.30571E+00 -0.10316E+01 -0.10316E+01
318 1.64400 -0.92348E+00 -0.29709E+00 -0.29709E+00 -0.99096E+00 -0.99096E+00
319 1.67600 -0.88958E+00 -0.29045E+00 -0.29045E+00 -0.95336E+00 -0.95336E+00
320 1.70800 -0.85751E+00 -0.28573E+00 -0.28573E+00 -0.91865E+00 -0.91865E+00
321 1.74000 -0.82706E+00 -0.28270E+00 -0.28270E+00 -0.88654E+00 -0.88654E+00
322 1.77200 -0.79820E+00 -0.28100E+00 -0.28100E+00 -0.85677E+00 -0.85677E+00
323 1.80400 -0.77075E+00 -0.28024E+00 -0.28024E+00 -0.82900E+00 -0.82900E+00
324 1.83600 -0.74470E+00 -0.28005E+00 -0.28005E+00 -0.80296E+00 -0.80296E+00
325 1.86800 -0.71989E+00 -0.28012E+00 -0.28012E+00 -0.77839E+00 -0.77839E+00
326 1.90000 -0.69630E+00 -0.28023E+00 -0.28023E+00 -0.75510E+00 -0.75510E+00
327 1.93200 -0.67380E+00 -0.28023E+00 -0.28023E+00 -0.73292E+00 -0.73292E+00
328 1.96400 -0.65238E+00 -0.28002E+00 -0.28002E+00 -0.71175E+00 -0.71175E+00
329 1.99600 -0.63192E+00 -0.27957E+00 -0.27957E+00 -0.69148E+00 -0.69148E+00
330 2.02800 -0.61243E+00 -0.27888E+00 -0.27888E+00 -0.67208E+00 -0.67208E+00
331 2.06000 -0.59378E+00 -0.27795E+00 -0.27795E+00 -0.65345E+00 -0.65345E+00
332 2.09200 -0.57600E+00 -0.27681E+00 -0.27681E+00 -0.63559E+00 -0.63559E+00
333 2.12400 -0.55897E+00 -0.27548E+00 -0.27548E+00 -0.61843E+00 -0.61843E+00
334 2.15600 -0.54270E+00 -0.27398E+00 -0.27398E+00 -0.60196E+00 -0.60196E+00
335 2.18800 -0.52711E+00 -0.27234E+00 -0.27234E+00 -0.58612E+00 -0.58612E+00
336 2.22000 -0.51221E+00 -0.27058E+00 -0.27058E+00 -0.57092E+00 -0.57092E+00
337 2.25200 -0.49791E+00 -0.26871E+00 -0.26871E+00 -0.55628E+00 -0.55628E+00
338 2.28400 -0.48423E+00 -0.26675E+00 -0.26675E+00 -0.54222E+00 -0.54222E+00
339 2.31600 -0.47109E+00 -0.26472E+00 -0.26472E+00 -0.52867E+00 -0.52867E+00
340 2.34800 -0.45851E+00 -0.26261E+00 -0.26261E+00 -0.51565E+00 -0.51565E+00
341 2.38000 -0.44641E+00 -0.26046E+00 -0.26046E+00 -0.50309E+00 -0.50309E+00
342 2.41200 -0.43482E+00 -0.25825E+00 -0.25825E+00 -0.49101E+00 -0.49101E+00
343 2.44400 -0.42366E+00 -0.25601E+00 -0.25601E+00 -0.47936E+00 -0.47936E+00
344 2.47600 -0.41296E+00 -0.25372E+00 -0.25372E+00 -0.46813E+00 -0.46813E+00
345 2.50800 -0.40266E+00 -0.25142E+00 -0.25142E+00 -0.45729E+00 -0.45729E+00
346 2.54000 -0.39277E+00 -0.24909E+00 -0.24909E+00 -0.44685E+00 -0.44685E+00
347 2.60400 -0.37405E+00 -0.24437E+00 -0.24437E+00 -0.42701E+00 -0.42701E+00
348 2.66800 -0.35677E+00 -0.23959E+00 -0.23959E+00 -0.40851E+00 -0.40851E+00
349 2.73200 -0.34067E+00 -0.23480E+00 -0.23480E+00 -0.39120E+00 -0.39120E+00
350 2.79600 -0.32577E+00 -0.23000E+00 -0.23000E+00 -0.37502E+00 -0.37502E+00
351 2.86000 -0.31184E+00 -0.22521E+00 -0.22521E+00 -0.35983E+00 -0.35983E+00
352 2.92400 -0.29892E+00 -0.22044E+00 -0.22044E+00 -0.34559E+00 -0.34559E+00
353 2.98800 -0.28681E+00 -0.21570E+00 -0.21570E+00 -0.33218E+00 -0.33218E+00
354 3.05200 -0.27555E+00 -0.21100E+00 -0.21100E+00 -0.31958E+00 -0.31958E+00
355 3.11600 -0.26497E+00 -0.20634E+00 -0.20634E+00 -0.30767E+00 -0.30767E+00
356 3.18000 -0.25511E+00 -0.20173E+00 -0.20173E+00 -0.29645E+00 -0.29645E+00
357 3.24400 -0.24582E+00 -0.19717E+00 -0.19717E+00 -0.28582E+00 -0.28582E+00
358 3.30800 -0.23714E+00 -0.19267E+00 -0.19267E+00 -0.27578E+00 -0.27578E+00
359 3.37200 -0.22896E+00 -0.18822E+00 -0.18822E+00 -0.26625E+00 -0.26625E+00
360 3.43600 -0.22128E+00 -0.18383E+00 -0.18383E+00 -0.25721E+00 -0.25721E+00
361 3.50000 -0.21403E+00 -0.17950E+00 -0.17950E+00 -0.24862E+00 -0.24862E+00
362 3.56400 -0.20723E+00 -0.17522E+00 -0.17522E+00 -0.24045E+00 -0.24045E+00
363 3.62800 -0.20078E+00 -0.17101E+00 -0.17101E+00 -0.23266E+00 -0.23266E+00
364 3.69200 -0.19471E+00 -0.16685E+00 -0.16685E+00 -0.22525E+00 -0.22525E+00
365 3.75600 -0.18895E+00 -0.16275E+00 -0.16275E+00 -0.21816E+00 -0.21816E+00
366 3.82000 -0.18352E+00 -0.15871E+00 -0.15871E+00 -0.21140E+00 -0.21140E+00
367 3.88400 -0.17836E+00 -0.15473E+00 -0.15473E+00 -0.20493E+00 -0.20493E+00
368 3.94800 -0.17348E+00 -0.15082E+00 -0.15082E+00 -0.19874E+00 -0.19874E+00
369 4.01200 -0.16884E+00 -0.14696E+00 -0.14696E+00 -0.19281E+00 -0.19281E+00
370 4.07600 -0.16444E+00 -0.14317E+00 -0.14317E+00 -0.18713E+00 -0.18713E+00
371 4.14000 -0.16024E+00 -0.13944E+00 -0.13944E+00 -0.18167E+00 -0.18167E+00
372 4.20400 -0.15626E+00 -0.13577E+00 -0.13577E+00 -0.17644E+00 -0.17644E+00
373 4.26800 -0.15246E+00 -0.13218E+00 -0.13218E+00 -0.17141E+00 -0.17141E+00
374 4.33200 -0.14885E+00 -0.12865E+00 -0.12865E+00 -0.16658E+00 -0.16658E+00
375 4.39600 -0.14539E+00 -0.12519E+00 -0.12519E+00 -0.16193E+00 -0.16193E+00
376 4.46000 -0.14210E+00 -0.12180E+00 -0.12180E+00 -0.15746E+00 -0.15746E+00
377 4.52400 -0.13894E+00 -0.11848E+00 -0.11848E+00 -0.15316E+00 -0.15316E+00
378 4.58800 -0.13593E+00 -0.11524E+00 -0.11524E+00 -0.14903E+00 -0.14903E+00
379 4.65200 -0.13305E+00 -0.11208E+00 -0.11208E+00 -0.14504E+00 -0.14504E+00
380 4.71600 -0.13029E+00 -0.10899E+00 -0.10899E+00 -0.14122E+00 -0.14122E+00
381 4.78000 -0.12764E+00 -0.10599E+00 -0.10599E+00 -0.13753E+00 -0.13753E+00
382 4.84400 -0.12510E+00 -0.10306E+00 -0.10306E+00 -0.13398E+00 -0.13398E+00
383 4.90800 -0.12266E+00 -0.10022E+00 -0.10022E+00 -0.13056E+00 -0.13056E+00
384 4.97200 -0.12032E+00 -0.97466E-01 -0.97466E-01 -0.12727E+00 -0.12727E+00
385 5.03600 -0.11807E+00 -0.94796E-01 -0.94796E-01 -0.12411E+00 -0.12411E+00
386 5.10000 -0.11590E+00 -0.92179E-01 -0.92179E-01 -0.12105E+00 -0.12105E+00
387 5.22800 -0.11180E+00 -0.87227E-01 -0.87227E-01 -0.11528E+00 -0.11528E+00
388 5.35600 -0.10801E+00 -0.82769E-01 -0.82769E-01 -0.11002E+00 -0.11002E+00
389 5.48400 -0.10446E+00 -0.78553E-01 -0.78553E-01 -0.10511E+00 -0.10511E+00
390 5.61200 -0.10116E+00 -0.74745E-01 -0.74745E-01 -0.10062E+00 -0.10062E+00
391 5.74000 -0.98065E-01 -0.71291E-01 -0.71291E-01 -0.96482E-01 -0.96482E-01
392 5.86800 -0.95170E-01 -0.68216E-01 -0.68216E-01 -0.92711E-01 -0.92711E-01
393 5.99600 -0.92443E-01 -0.65512E-01 -0.65512E-01 -0.89276E-01 -0.89276E-01
394 6.12400 -0.89883E-01 -0.63184E-01 -0.63184E-01 -0.86170E-01 -0.86170E-01
395 6.25200 -0.87463E-01 -0.61228E-01 -0.61228E-01 -0.83374E-01 -0.83374E-01
396 6.38000 -0.85182E-01 -0.59642E-01 -0.59642E-01 -0.80880E-01 -0.80880E-01
397 6.50800 -0.83019E-01 -0.58416E-01 -0.58416E-01 -0.78668E-01 -0.78668E-01
398 6.63600 -0.80972E-01 -0.57536E-01 -0.57536E-01 -0.76728E-01 -0.76728E-01
399 6.76400 -0.79026E-01 -0.56982E-01 -0.56982E-01 -0.75036E-01 -0.75036E-01
400 6.89200 -0.77178E-01 -0.56723E-01 -0.56723E-01 -0.73573E-01 -0.73573E-01
401 7.02000 -0.75417E-01 -0.56719E-01 -0.56719E-01 -0.72311E-01 -0.72311E-01
402 7.14800 -0.73740E-01 -0.56920E-01 -0.56920E-01 -0.71221E-01 -0.71221E-01
403 7.27600 -0.72138E-01 -0.57265E-01 -0.57265E-01 -0.70266E-01 -0.70266E-01
404 7.40400 -0.70608E-01 -0.57687E-01 -0.57687E-01 -0.69407E-01 -0.69407E-01
405 7.53200 -0.69144E-01 -0.58111E-01 -0.58111E-01 -0.68603E-01 -0.68603E-01
406 7.66000 -0.67742E-01 -0.58459E-01 -0.58459E-01 -0.67811E-01 -0.67811E-01
407 7.78800 -0.66397E-01 -0.58657E-01 -0.58657E-01 -0.66990E-01 -0.66990E-01
408 7.91600 -0.65107E-01 -0.58635E-01 -0.58635E-01 -0.66104E-01 -0.66104E-01
409 8.04400 -0.63867E-01 -0.58337E-01 -0.58337E-01 -0.65119E-01 -0.65119E-01
410 8.17200 -0.62676E-01 -0.57718E-01 -0.57718E-01 -0.64012E-01 -0.64012E-01
411 8.30000 -0.61529E-01 -0.56754E-01 -0.56754E-01 -0.62766E-01 -0.62766E-01
412 8.42800 -0.60424E-01 -0.55435E-01 -0.55435E-01 -0.61377E-01 -0.61377E-01
413 8.55600 -0.59359E-01 -0.53772E-01 -0.53772E-01 -0.59846E-01 -0.59846E-01
414 8.68400 -0.58332E-01 -0.51790E-01 -0.51790E-01 -0.58185E-01 -0.58185E-01
415 8.81200 -0.57341E-01 -0.49529E-01 -0.49529E-01 -0.56411E-01 -0.56411E-01
416 8.94000 -0.56383E-01 -0.47038E-01 -0.47038E-01 -0.54548E-01 -0.54548E-01
417 9.06800 -0.55457E-01 -0.44369E-01 -0.44369E-01 -0.52620E-01 -0.52620E-01
418 9.19600 -0.54562E-01 -0.41581E-01 -0.41581E-01 -0.50655E-01 -0.50655E-01
419 9.32400 -0.53695E-01 -0.38728E-01 -0.38728E-01 -0.48679E-01 -0.48679E-01
420 9.45200 -0.52856E-01 -0.35862E-01 -0.35862E-01 -0.46717E-01 -0.46717E-01
421 9.58000 -0.52042E-01 -0.33028E-01 -0.33028E-01 -0.44790E-01 -0.44790E-01
422 9.70800 -0.51254E-01 -0.30266E-01 -0.30266E-01 -0.42917E-01 -0.42917E-01
423 9.83600 -0.50489E-01 -0.27608E-01 -0.27608E-01 -0.41113E-01 -0.41113E-01
424 9.96400 -0.49746E-01 -0.25075E-01 -0.25075E-01 -0.39388E-01 -0.39388E-01
425 10.09200 -0.49025E-01 -0.22687E-01 -0.22687E-01 -0.37750E-01 -0.37750E-01
426 10.22000 -0.48325E-01 -0.20526E-01 -0.20526E-01 -0.36241E-01 -0.36241E-01
427 10.47600 -0.46982E-01 -0.16523E-01 -0.16523E-01 -0.33423E-01 -0.33423E-01
428 10.73200 -0.45712E-01 -0.13072E-01 -0.13072E-01 -0.30931E-01 -0.30931E-01
429 10.98800 -0.44508E-01 -0.10367E-01 -0.10367E-01 -0.28859E-01 -0.28859E-01
430 11.24400 -0.43365E-01 -0.81480E-02 -0.81480E-02 -0.27071E-01 -0.27071E-01
431 11.50000 -0.42278E-01 -0.63810E-02 -0.63810E-02 -0.25547E-01 -0.25547E-01
432 11.75600 -0.41244E-01 -0.49785E-02 -0.49785E-02 -0.24241E-01 -0.24241E-01
433 12.01200 -0.40258E-01 -0.38752E-02 -0.38752E-02 -0.23116E-01 -0.23116E-01
434 12.26800 -0.39317E-01 -0.30111E-02 -0.30111E-02 -0.22140E-01 -0.22140E-01
435 12.52400 -0.38418E-01 -0.23370E-02 -0.23370E-02 -0.21287E-01 -0.21287E-01
436 12.78000 -0.37559E-01 -0.18126E-02 -0.18126E-02 -0.20534E-01 -0.20534E-01
437 13.03600 -0.36735E-01 -0.14055E-02 -0.14055E-02 -0.19863E-01 -0.19863E-01
438 13.29200 -0.35947E-01 -0.10897E-02 -0.10897E-02 -0.19259E-01 -0.19259E-01
439 13.54800 -0.35190E-01 -0.84505E-03 -0.84505E-03 -0.18711E-01 -0.18711E-01
440 13.80400 -0.34463E-01 -0.65552E-03 -0.65552E-03 -0.18209E-01 -0.18209E-01
441 14.06000 -0.33765E-01 -0.50871E-03 -0.50871E-03 -0.17746E-01 -0.17746E-01
442 14.31600 -0.33093E-01 -0.39498E-03 -0.39498E-03 -0.17316E-01 -0.17316E-01
443 14.57200 -0.32446E-01 -0.30685E-03 -0.30685E-03 -0.16915E-01 -0.16915E-01
444 14.82800 -0.31824E-01 -0.23853E-03 -0.23853E-03 -0.16538E-01 -0.16538E-01
445 15.08400 -0.31223E-01 -0.18554E-03 -0.18554E-03 -0.16181E-01 -0.16181E-01
446 15.34000 -0.30644E-01 -0.14441E-03 -0.14441E-03 -0.15844E-01 -0.15844E-01
447 15.59600 -0.30085E-01 -0.11247E-03 -0.11247E-03 -0.15523E-01 -0.15523E-01
448 15.85200 -0.29545E-01 -0.87651E-04 -0.87651E-04 -0.15217E-01 -0.15217E-01
449 16.10800 -0.29024E-01 -0.68351E-04 -0.68351E-04 -0.14925E-01 -0.14925E-01
450 16.36400 -0.28519E-01 -0.53333E-04 -0.53333E-04 -0.14645E-01 -0.14645E-01
451 16.62000 -0.28031E-01 -0.41639E-04 -0.41639E-04 -0.14375E-01 -0.14375E-01
452 16.87600 -0.27558E-01 -0.32528E-04 -0.32528E-04 -0.14117E-01 -0.14117E-01
453 17.13200 -0.27100E-01 -0.25424E-04 -0.25424E-04 -0.13867E-01 -0.13867E-01
454 17.38800 -0.26656E-01 -0.19882E-04 -0.19882E-04 -0.13627E-01 -0.13627E-01
455 17.64400 -0.26226E-01 -0.15556E-04 -0.15556E-04 -0.13395E-01 -0.13395E-01
456 17.90000 -0.25808E-01 -0.12176E-04 -0.12176E-04 -0.13171E-01 -0.13171E-01
457 18.15600 -0.25403E-01 -0.95354E-05 -0.95354E-05 -0.12954E-01 -0.12954E-01
458 18.41200 -0.25009E-01 -0.74700E-05 -0.74700E-05 -0.12744E-01 -0.12744E-01
459 18.66800 -0.24627E-01 -0.58546E-05 -0.58546E-05 -0.12541E-01 -0.12541E-01
460 18.92400 -0.24255E-01 -0.45881E-05 -0.45881E-05 -0.12344E-01 -0.12344E-01
461 19.18000 -0.23894E-01 -0.36023E-05 -0.36023E-05 -0.12153E-01 -0.12153E-01
462 19.43600 -0.23543E-01 -0.28114E-05 -0.28114E-05 -0.11967E-01 -0.11967E-01
463 19.69200 -0.23201E-01 -0.22450E-05 -0.22450E-05 -0.11787E-01 -0.11787E-01
464 19.94800 -0.22868E-01 -0.16590E-05 -0.16590E-05 -0.11612E-01 -0.11612E-01
465 20.20400 -0.22544E-01 -0.15366E-05 -0.15366E-05 -0.11442E-01 -0.11442E-01
466 20.46000 -0.22228E-01 -0.13842E-05 -0.13842E-05 -0.11277E-01 -0.11277E-01
467
468
469
470 ********************* iteration: 2 ***********************
471
472 l = 0, 5 bound states
473 l = 1, 3 bound states
474 l = 2, 1 bound states
475 l = 0, 5 bound states
476 l = 1, 3 bound states
477 l = 2, 1 bound states
478
479
480 bound states
481
482 100 energy: -54.47671 iteration loops: 6
483 200 energy: -4.17535 iteration loops: 11
484 300 energy: -0.29422 iteration loops: 12
485 210 energy: -2.79007 iteration loops: 8
486 310 energy: -0.11055 iteration loops: 9
487 100 energy: -54.47671 iteration loops: 6
488 200 energy: -4.17535 iteration loops: 11
489 300 energy: -0.29422 iteration loops: 12
490 210 energy: -2.79007 iteration loops: 8
491
492 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
493 induced moment: 1.00000
494
495 energy terms
496 energy eigenvalue sum: -0.134744E+03
497 kin: 0.187132E+03 0.186409E+03 coul: -0.468433E+03 exc: -0.184789E+02
498
499 total energy: -0.2481140E+03
500 valence energy: -0.2422917E+03
501
502
503
504 ********************* iteration: 3 ***********************
505
506 l = 0, 5 bound states
507 l = 1, 3 bound states
508 l = 2, 1 bound states
509 l = 0, 5 bound states
510 l = 1, 3 bound states
511 l = 2, 1 bound states
512
513
514 bound states
515
516 100 energy: -55.36892 iteration loops: 5
517 200 energy: -4.29777 iteration loops: 5
518 300 energy: -0.36089 iteration loops: 7
519 210 energy: -2.91215 iteration loops: 6
520 310 energy: -0.16411 iteration loops: 8
521 100 energy: -55.36808 iteration loops: 5
522 200 energy: -4.29667 iteration loops: 5
523 300 energy: -0.34758 iteration loops: 7
524 210 energy: -2.91076 iteration loops: 6
525
526 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
527 induced moment: 1.00000
528
529 energy terms
530 energy eigenvalue sum: -0.137673E+03
531 kin: 0.190704E+03 0.189800E+03 coul: -0.470290E+03 exc: -0.186975E+02
532
533 total energy: -0.2461560E+03
534 valence energy: -0.2469787E+03
535
536
537
538 ********************* iteration: 4 ***********************
539
540 l = 0, 5 bound states
541 l = 1, 3 bound states
542 l = 2, 1 bound states
543 l = 0, 4 bound states
544 l = 1, 3 bound states
545
546
547 bound states
548
549 100 energy: -55.55097 iteration loops: 4
550 200 energy: -4.20776 iteration loops: 4
551 300 energy: -0.35526 iteration loops: 7
552 210 energy: -2.81804 iteration loops: 5
553 310 energy: -0.15966 iteration loops: 6
554 100 energy: -55.54955 iteration loops: 4
555 200 energy: -4.20596 iteration loops: 4
556 300 energy: -0.33342 iteration loops: 6
557 210 energy: -2.81575 iteration loops: 5
558
559 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
560 induced moment: 1.00000
561
562 energy terms
563 energy eigenvalue sum: -0.137264E+03
564 kin: 0.190734E+03 0.189832E+03 coul: -0.468741E+03 exc: -0.186828E+02
565
566 total energy: -0.2441225E+03
567 valence energy: -0.2463262E+03
568
569
570
571 ********************* iteration: 5 ***********************
572
573 l = 0, 4 bound states
574 l = 1, 3 bound states
575 l = 0, 4 bound states
576 l = 1, 2 bound states
577
578
579 bound states
580
581 100 energy: -55.51177 iteration loops: 4
582 200 energy: -4.09189 iteration loops: 5
583 300 energy: -0.33274 iteration loops: 6
584 210 energy: -2.69809 iteration loops: 6
585 310 energy: -0.14172 iteration loops: 8
586 100 energy: -55.51008 iteration loops: 4
587 200 energy: -4.08978 iteration loops: 5
588 300 energy: -0.30655 iteration loops: 5
589 210 energy: -2.69538 iteration loops: 6
590
591 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
592 induced moment: 1.00000
593
594 energy terms
595 energy eigenvalue sum: -0.136165E+03
596 kin: 0.189870E+03 0.189016E+03 coul: -0.466985E+03 exc: -0.186108E+02
597
598 total energy: -0.2428752E+03
599 valence energy: -0.2445257E+03
600
601
602
603 ********************* iteration: 6 ***********************
604
605 l = 0, 4 bound states
606 l = 1, 3 bound states
607 l = 0, 4 bound states
608 l = 1, 2 bound states
609
610
611 bound states
612
613 100 energy: -55.45132 iteration loops: 4
614 200 energy: -4.01239 iteration loops: 4
615 300 energy: -0.31424 iteration loops: 5
616 210 energy: -2.61641 iteration loops: 5
617 310 energy: -0.12716 iteration loops: 9
618 100 energy: -55.44954 iteration loops: 4
619 200 energy: -4.01021 iteration loops: 4
620 300 energy: -0.28628 iteration loops: 5
621 210 energy: -2.61358 iteration loops: 5
622
623 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
624 induced moment: 1.00000
625
626 energy terms
627 energy eigenvalue sum: -0.135341E+03
628 kin: 0.189155E+03 0.188346E+03 coul: -0.465936E+03 exc: -0.185527E+02
629
630 total energy: -0.2423289E+03
631 valence energy: -0.2431501E+03
632
633
634
635 ********************* iteration: 7 ***********************
636
637 l = 0, 4 bound states
638 l = 1, 3 bound states
639 l = 0, 4 bound states
640 l = 1, 2 bound states
641
642
643 bound states
644
645 100 energy: -55.42092 iteration loops: 3
646 200 energy: -3.97283 iteration loops: 5
647 300 energy: -0.30360 iteration loops: 5
648 210 energy: -2.57639 iteration loops: 5
649 310 energy: -0.11875 iteration loops: 5
650 100 energy: -55.41915 iteration loops: 3
651 200 energy: -3.97066 iteration loops: 5
652 300 energy: -0.27518 iteration loops: 5
653 210 energy: -2.57357 iteration loops: 5
654
655 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
656 induced moment: 1.00000
657
658 energy terms
659 energy eigenvalue sum: -0.134931E+03
660 kin: 0.188797E+03 0.188014E+03 coul: -0.465552E+03 exc: -0.185233E+02
661
662 total energy: -0.2421949E+03
663 valence energy: -0.2424598E+03
664
665
666
667 ********************* iteration: 8 ***********************
668
669 l = 0, 4 bound states
670 l = 1, 2 bound states
671 l = 0, 4 bound states
672 l = 1, 2 bound states
673
674
675 bound states
676
677 100 energy: -55.41596 iteration loops: 3
678 200 energy: -3.95882 iteration loops: 5
679 300 energy: -0.29885 iteration loops: 5
680 210 energy: -2.56284 iteration loops: 4
681 310 energy: -0.11484 iteration loops: 5
682 100 energy: -55.41421 iteration loops: 3
683 200 energy: -3.95669 iteration loops: 5
684 300 energy: -0.27046 iteration loops: 5
685 210 energy: -2.56007 iteration loops: 4
686
687 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
688 induced moment: 1.00000
689
690 energy terms
691 energy eigenvalue sum: -0.134799E+03
692 kin: 0.188694E+03 0.187922E+03 coul: -0.465531E+03 exc: -0.185148E+02
693
694 total energy: -0.2422287E+03
695 valence energy: -0.2422434E+03
696
697
698
699 ********************* iteration: 9 ***********************
700
701 l = 0, 4 bound states
702 l = 1, 2 bound states
703 l = 0, 4 bound states
704 l = 1, 2 bound states
705
706
707 bound states
708
709 100 energy: -55.42156 iteration loops: 4
710 200 energy: -3.95653 iteration loops: 4
711 300 energy: -0.29725 iteration loops: 5
712 210 energy: -2.56125 iteration loops: 4
713 310 energy: -0.11332 iteration loops: 5
714 100 energy: -55.41983 iteration loops: 4
715 200 energy: -3.95443 iteration loops: 4
716 300 energy: -0.26899 iteration loops: 5
717 210 energy: -2.55852 iteration loops: 4
718
719 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
720 induced moment: 1.00000
721
722 energy terms
723 energy eigenvalue sum: -0.134791E+03
724 kin: 0.188705E+03 0.187936E+03 coul: -0.465626E+03 exc: -0.185158E+02
725
726 total energy: -0.2422928E+03
727 valence energy: -0.2422437E+03
728
729
730
731 ********************* iteration: 10 ***********************
732
733 l = 0, 4 bound states
734 l = 1, 2 bound states
735 l = 0, 4 bound states
736 l = 1, 2 bound states
737
738
739 bound states
740
741 100 energy: -55.42793 iteration loops: 4
742 200 energy: -3.95770 iteration loops: 4
743 300 energy: -0.29690 iteration loops: 4
744 210 energy: -2.56301 iteration loops: 4
745 310 energy: -0.11279 iteration loops: 5
746 100 energy: -55.42622 iteration loops: 4
747 200 energy: -3.95562 iteration loops: 4
748 300 energy: -0.26872 iteration loops: 4
749 210 energy: -2.56031 iteration loops: 4
750
751 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
752 induced moment: 1.00000
753
754 energy terms
755 energy eigenvalue sum: -0.134816E+03
756 kin: 0.188741E+03 0.187972E+03 coul: -0.465715E+03 exc: -0.185191E+02
757
758 total energy: -0.2423368E+03
759 valence energy: -0.2422989E+03
760
761
762
763 ********************* iteration: 11 ***********************
764
765 l = 0, 4 bound states
766 l = 1, 2 bound states
767 l = 0, 4 bound states
768 l = 1, 2 bound states
769
770
771 bound states
772
773 100 energy: -55.43163 iteration loops: 3
774 200 energy: -3.95890 iteration loops: 4
775 300 energy: -0.29685 iteration loops: 4
776 210 energy: -2.56458 iteration loops: 3
777 310 energy: -0.11256 iteration loops: 5
778 100 energy: -55.42992 iteration loops: 3
779 200 energy: -3.95682 iteration loops: 4
780 300 energy: -0.26871 iteration loops: 4
781 210 energy: -2.56189 iteration loops: 3
782
783 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
784 induced moment: 1.00000
785
786 energy terms
787 energy eigenvalue sum: -0.134835E+03
788 kin: 0.188768E+03 0.187998E+03 coul: -0.465764E+03 exc: -0.185217E+02
789
790 total energy: -0.2423554E+03
791 valence energy: -0.2423421E+03
792
793
794
795 ********************* iteration: 12 ***********************
796
797 l = 0, 4 bound states
798 l = 1, 2 bound states
799 l = 0, 4 bound states
800 l = 1, 2 bound states
801
802
803 bound states
804
805 100 energy: -55.43277 iteration loops: 3
806 200 energy: -3.95934 iteration loops: 4
807 300 energy: -0.29679 iteration loops: 4
808 210 energy: -2.56521 iteration loops: 3
809 310 energy: -0.11238 iteration loops: 5
810 100 energy: -55.43107 iteration loops: 3
811 200 energy: -3.95727 iteration loops: 4
812 300 energy: -0.26864 iteration loops: 4
813 210 energy: -2.56252 iteration loops: 3
814
815 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
816 induced moment: 1.00000
817
818 energy terms
819 energy eigenvalue sum: -0.134841E+03
820 kin: 0.188779E+03 0.188008E+03 coul: -0.465781E+03 exc: -0.185229E+02
821
822 total energy: -0.2423586E+03
823 valence energy: -0.2423610E+03
824
825
826
827 ********************* iteration: 13 ***********************
828
829 l = 0, 4 bound states
830 l = 1, 2 bound states
831 l = 0, 4 bound states
832 l = 1, 2 bound states
833
834
835 bound states
836
837 100 energy: -55.43252 iteration loops: 3
838 200 energy: -3.95924 iteration loops: 3
839 300 energy: -0.29667 iteration loops: 4
840 210 energy: -2.56520 iteration loops: 3
841 310 energy: -0.11222 iteration loops: 4
842 100 energy: -55.43081 iteration loops: 3
843 200 energy: -3.95717 iteration loops: 3
844 300 energy: -0.26851 iteration loops: 4
845 210 energy: -2.56251 iteration loops: 3
846
847 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
848 induced moment: 1.00000
849
850 energy terms
851 energy eigenvalue sum: -0.134840E+03
852 kin: 0.188780E+03 0.188009E+03 coul: -0.465781E+03 exc: -0.185232E+02
853
854 total energy: -0.2423557E+03
855 valence energy: -0.2423635E+03
856
857
858
859 ********************* iteration: 14 ***********************
860
861 l = 0, 4 bound states
862 l = 1, 2 bound states
863 l = 0, 4 bound states
864 l = 1, 2 bound states
865
866
867 bound states
868
869 100 energy: -55.43184 iteration loops: 4
870 200 energy: -3.95896 iteration loops: 4
871 300 energy: -0.29655 iteration loops: 4
872 210 energy: -2.56494 iteration loops: 3
873 310 energy: -0.11208 iteration loops: 4
874 100 energy: -55.43013 iteration loops: 4
875 200 energy: -3.95688 iteration loops: 4
876 300 energy: -0.26838 iteration loops: 4
877 210 energy: -2.56225 iteration loops: 3
878
879 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
880 induced moment: 1.00000
881
882 energy terms
883 energy eigenvalue sum: -0.134836E+03
884 kin: 0.188777E+03 0.188007E+03 coul: -0.465777E+03 exc: -0.185231E+02
885
886 total energy: -0.2423522E+03
887 valence energy: -0.2423593E+03
888
889
890
891 ********************* iteration: 15 ***********************
892
893 l = 0, 4 bound states
894 l = 1, 2 bound states
895 l = 0, 4 bound states
896 l = 1, 2 bound states
897
898
899 bound states
900
901 100 energy: -55.43124 iteration loops: 3
902 200 energy: -3.95870 iteration loops: 4
903 300 energy: -0.29644 iteration loops: 4
904 210 energy: -2.56469 iteration loops: 3
905 310 energy: -0.11199 iteration loops: 4
906 100 energy: -55.42953 iteration loops: 3
907 200 energy: -3.95663 iteration loops: 4
908 300 energy: -0.26827 iteration loops: 4
909 210 energy: -2.56199 iteration loops: 3
910
911 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
912 induced moment: 1.00000
913
914 energy terms
915 energy eigenvalue sum: -0.134833E+03
916 kin: 0.188774E+03 0.188004E+03 coul: -0.465772E+03 exc: -0.185230E+02
917
918 total energy: -0.2423499E+03
919 valence energy: -0.2423544E+03
920
921
922
923 ********************* iteration: 16 ***********************
924
925 l = 0, 4 bound states
926 l = 1, 2 bound states
927 l = 0, 4 bound states
928 l = 1, 2 bound states
929
930
931 bound states
932
933 100 energy: -55.43086 iteration loops: 3
934 200 energy: -3.95854 iteration loops: 3
935 300 energy: -0.29638 iteration loops: 4
936 210 energy: -2.56452 iteration loops: 3
937 310 energy: -0.11193 iteration loops: 4
938 100 energy: -55.42915 iteration loops: 3
939 200 energy: -3.95646 iteration loops: 3
940 300 energy: -0.26820 iteration loops: 4
941 210 energy: -2.56183 iteration loops: 3
942
943 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
944 induced moment: 1.00000
945
946 energy terms
947 energy eigenvalue sum: -0.134831E+03
948 kin: 0.188772E+03 0.188002E+03 coul: -0.465769E+03 exc: -0.185228E+02
949
950 total energy: -0.2423489E+03
951 valence energy: -0.2423511E+03
952
953
954
955 ********************* iteration: 17 ***********************
956
957 l = 0, 4 bound states
958 l = 1, 2 bound states
959 l = 0, 4 bound states
960 l = 1, 2 bound states
961
962
963 bound states
964
965 100 energy: -55.43068 iteration loops: 2
966 200 energy: -3.95846 iteration loops: 3
967 300 energy: -0.29634 iteration loops: 4
968 210 energy: -2.56445 iteration loops: 3
969 310 energy: -0.11190 iteration loops: 4
970 100 energy: -55.42897 iteration loops: 2
971 200 energy: -3.95639 iteration loops: 3
972 300 energy: -0.26817 iteration loops: 4
973 210 energy: -2.56176 iteration loops: 3
974
975 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
976 induced moment: 1.00000
977
978 energy terms
979 energy eigenvalue sum: -0.134830E+03
980 kin: 0.188771E+03 0.188001E+03 coul: -0.465769E+03 exc: -0.185228E+02
981
982 total energy: -0.2423487E+03
983 valence energy: -0.2423495E+03
984
985
986
987 ********************* iteration: 18 ***********************
988
989 l = 0, 4 bound states
990 l = 1, 2 bound states
991 l = 0, 4 bound states
992 l = 1, 2 bound states
993
994
995 bound states
996
997 100 energy: -55.43062 iteration loops: 2
998 200 energy: -3.95843 iteration loops: 3
999 300 energy: -0.29633 iteration loops: 4
1000 210 energy: -2.56442 iteration loops: 3
1001 310 energy: -0.11188 iteration loops: 4
1002 100 energy: -55.42891 iteration loops: 2
1003 200 energy: -3.95636 iteration loops: 3
1004 300 energy: -0.26815 iteration loops: 4
1005 210 energy: -2.56173 iteration loops: 3
1006
1007 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1008 induced moment: 1.00000
1009
1010 energy terms
1011 energy eigenvalue sum: -0.134829E+03
1012 kin: 0.188771E+03 0.188001E+03 coul: -0.465769E+03 exc: -0.185228E+02
1013
1014 total energy: -0.2423488E+03
1015 valence energy: -0.2423489E+03
1016
1017
1018
1019 ********************* iteration: 19 ***********************
1020
1021 l = 0, 4 bound states
1022 l = 1, 2 bound states
1023 l = 0, 4 bound states
1024 l = 1, 2 bound states
1025
1026
1027 bound states
1028
1029 100 energy: -55.43060 iteration loops: 2
1030 200 energy: -3.95843 iteration loops: 3
1031 300 energy: -0.29632 iteration loops: 3
1032 210 energy: -2.56442 iteration loops: 3
1033 310 energy: -0.11188 iteration loops: 4
1034 100 energy: -55.42889 iteration loops: 2
1035 200 energy: -3.95636 iteration loops: 3
1036 300 energy: -0.26814 iteration loops: 3
1037 210 energy: -2.56173 iteration loops: 3
1038
1039 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1040 induced moment: 1.00000
1041
1042 energy terms
1043 energy eigenvalue sum: -0.134829E+03
1044 kin: 0.188771E+03 0.188001E+03 coul: -0.465769E+03 exc: -0.185228E+02
1045
1046 total energy: -0.2423489E+03
1047 valence energy: -0.2423488E+03
1048
1049
1050
1051 ********************* iteration: 20 ***********************
1052
1053 l = 0, 4 bound states
1054 l = 1, 2 bound states
1055 l = 0, 4 bound states
1056 l = 1, 2 bound states
1057
1058
1059 bound states
1060
1061 100 energy: -55.43060 iteration loops: 2
1062 200 energy: -3.95844 iteration loops: 3
1063 300 energy: -0.29632 iteration loops: 3
1064 210 energy: -2.56443 iteration loops: 3
1065 310 energy: -0.11188 iteration loops: 3
1066 100 energy: -55.42889 iteration loops: 2
1067 200 energy: -3.95636 iteration loops: 3
1068 300 energy: -0.26814 iteration loops: 3
1069 210 energy: -2.56174 iteration loops: 3
1070
1071 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1072 induced moment: 1.00000
1073
1074 energy terms
1075 energy eigenvalue sum: -0.134829E+03
1076 kin: 0.188771E+03 0.188000E+03 coul: -0.465768E+03 exc: -0.185228E+02
1077
1078 total energy: -0.2423490E+03
1079 valence energy: -0.2423489E+03
1080
1081
1082
1083 ********************* iteration: 21 ***********************
1084
1085 l = 0, 4 bound states
1086 l = 1, 2 bound states
1087 l = 0, 4 bound states
1088 l = 1, 2 bound states
1089
1090
1091 bound states
1092
1093 100 energy: -55.43061 iteration loops: 7
1094 200 energy: -3.95844 iteration loops: 3
1095 300 energy: -0.29632 iteration loops: 3
1096 210 energy: -2.56443 iteration loops: 3
1097 310 energy: -0.11188 iteration loops: 3
1098 100 energy: -55.42890 iteration loops: 2
1099 200 energy: -3.95637 iteration loops: 3
1100 300 energy: -0.26814 iteration loops: 3
1101 210 energy: -2.56174 iteration loops: 3
1102
1103 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1104 induced moment: 1.00000
1105
1106 energy terms
1107 energy eigenvalue sum: -0.134829E+03
1108 kin: 0.188771E+03 0.188000E+03 coul: -0.465769E+03 exc: -0.185228E+02
1109
1110 total energy: -0.2423491E+03
1111 valence energy: -0.2423490E+03
1112
1113
1114
1115 ********************* iteration: 22 ***********************
1116
1117 l = 0, 4 bound states
1118 l = 1, 2 bound states
1119 l = 0, 4 bound states
1120 l = 1, 2 bound states
1121
1122
1123 bound states
1124
1125 100 energy: -55.43061 iteration loops: 2
1126 200 energy: -3.95844 iteration loops: 3
1127 300 energy: -0.29632 iteration loops: 3
1128 210 energy: -2.56444 iteration loops: 3
1129 310 energy: -0.11188 iteration loops: 3
1130 100 energy: -55.42890 iteration loops: 2
1131 200 energy: -3.95637 iteration loops: 3
1132 300 energy: -0.26815 iteration loops: 3
1133 210 energy: -2.56174 iteration loops: 3
1134
1135 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1136 induced moment: 1.00000
1137
1138 energy terms
1139 energy eigenvalue sum: -0.134829E+03
1140 kin: 0.188771E+03 0.188000E+03 coul: -0.465769E+03 exc: -0.185228E+02
1141
1142 total energy: -0.2423491E+03
1143 valence energy: -0.2423491E+03
1144
1145
1146
1147 ********************* iteration: 23 ***********************
1148
1149 l = 0, 4 bound states
1150 l = 1, 2 bound states
1151 l = 0, 4 bound states
1152 l = 1, 2 bound states
1153
1154
1155 bound states
1156
1157 100 energy: -55.43061 iteration loops: 2
1158 200 energy: -3.95844 iteration loops: 3
1159 300 energy: -0.29632 iteration loops: 3
1160 210 energy: -2.56444 iteration loops: 3
1161 310 energy: -0.11188 iteration loops: 3
1162 100 energy: -55.42890 iteration loops: 2
1163 200 energy: -3.95637 iteration loops: 3
1164 300 energy: -0.26815 iteration loops: 3
1165 210 energy: -2.56174 iteration loops: 3
1166
1167 integr charges: total 13.0000001 valence: 13.0000001 0.0000000
1168 induced moment: 1.00000
1169
1170 energy terms
1171 energy eigenvalue sum: -0.134829E+03
1172 kin: 0.188771E+03 0.188000E+03 coul: -0.465769E+03 exc: -0.185228E+02
1173
1174 total energy: -0.2423491E+03
1175 valence energy: -0.2423491E+03
diff --git a/src/labat/atomctrl.dat b/src/labat/atomctrl.dat
new file mode 100644
index 0000000..6fa2eee
--- /dev/null
+++ b/src/labat/atomctrl.dat
@@ -0,0 +1,15 @@
113 0
210 40 0.2000
30.5000 0.00001 0.005
430 0 1 0
55 2 2
6100 -84.5000 1 1 0
7200 -16.2450 1 1 0
8210 -5.3356 3 1 0
9300 -0.7812 1 1 0
10310 -0.2312 1 1 0
11100 -84.5000 1 1 0
12200 -16.2450 1 1 0
13210 -5.3356 3 1 0
14300 -0.7812 1 1 0
15310 -0.2312 0 1 0
diff --git a/src/labat/atomdens.dat b/src/labat/atomdens.dat
new file mode 100644
index 0000000..65d8de7
--- /dev/null
+++ b/src/labat/atomdens.dat
@@ -0,0 +1,401 @@
1 0.000000000000E+00 0.000000000000E+00 0.000000000000E+00
2 0.500000000000E-03 0.436175457142E-02 0.000000000000E+00
3 0.100000000000E-02 0.172211515283E-01 0.000000000000E+00
4 0.150000000000E-02 0.382459117112E-01 0.000000000000E+00
5 0.200000000000E-02 0.671124120455E-01 0.000000000000E+00
6 0.250000000000E-02 0.103505537733E+00 0.000000000000E+00
7 0.300000000000E-02 0.147118470048E+00 0.000000000000E+00
8 0.350000000000E-02 0.197652522367E+00 0.000000000000E+00
9 0.400000000000E-02 0.254816957219E+00 0.000000000000E+00
10 0.450000000000E-02 0.318328815746E+00 0.000000000000E+00
11 0.500000000000E-02 0.387912747299E+00 0.000000000000E+00
12 0.550000000000E-02 0.463300842732E+00 0.000000000000E+00
13 0.600000000000E-02 0.544232471462E+00 0.000000000000E+00
14 0.650000000000E-02 0.630454120441E+00 0.000000000000E+00
15 0.700000000000E-02 0.721719237721E+00 0.000000000000E+00
16 0.750000000000E-02 0.817788077185E+00 0.000000000000E+00
17 0.800000000000E-02 0.918427548340E+00 0.000000000000E+00
18 0.850000000000E-02 0.102341106664E+01 0.000000000000E+00
19 0.900000000000E-02 0.113251840931E+01 0.000000000000E+00
20 0.950000000000E-02 0.124553557108E+01 0.000000000000E+00
21 0.100000000000E-01 0.136225462590E+01 0.000000000000E+00
22 0.105000000000E-01 0.148247358782E+01 0.000000000000E+00
23 0.110000000000E-01 0.160599627846E+01 0.000000000000E+00
24 0.115000000000E-01 0.173263219287E+01 0.000000000000E+00
25 0.120000000000E-01 0.186219637254E+01 0.000000000000E+00
26 0.125000000000E-01 0.199450927612E+01 0.000000000000E+00
27 0.130000000000E-01 0.212939665777E+01 0.000000000000E+00
28 0.135000000000E-01 0.226668944255E+01 0.000000000000E+00
29 0.140000000000E-01 0.240622360993E+01 0.000000000000E+00
30 0.145000000000E-01 0.254784007371E+01 0.000000000000E+00
31 0.150000000000E-01 0.269138457059E+01 0.000000000000E+00
32 0.155000000000E-01 0.283670754435E+01 0.000000000000E+00
33 0.160000000000E-01 0.298366403931E+01 0.000000000000E+00
34 0.165000000000E-01 0.313211358875E+01 0.000000000000E+00
35 0.170000000000E-01 0.328192011295E+01 0.000000000000E+00
36 0.175000000000E-01 0.343295181175E+01 0.000000000000E+00
37 0.180000000000E-01 0.358508106710E+01 0.000000000000E+00
38 0.185000000000E-01 0.373818433947E+01 0.000000000000E+00
39 0.190000000000E-01 0.389214207482E+01 0.000000000000E+00
40 0.195000000000E-01 0.404683860473E+01 0.000000000000E+00
41 0.200000000000E-01 0.420216205770E+01 0.000000000000E+00
42 0.210000000000E-01 0.451426066096E+01 0.000000000000E+00
43 0.220000000000E-01 0.482761538713E+01 0.000000000000E+00
44 0.230000000000E-01 0.514145874839E+01 0.000000000000E+00
45 0.240000000000E-01 0.545507568127E+01 0.000000000000E+00
46 0.250000000000E-01 0.576780090940E+01 0.000000000000E+00
47 0.260000000000E-01 0.607901658509E+01 0.000000000000E+00
48 0.270000000000E-01 0.638814985059E+01 0.000000000000E+00
49 0.280000000000E-01 0.669467068676E+01 0.000000000000E+00
50 0.290000000000E-01 0.699808966255E+01 0.000000000000E+00
51 0.300000000000E-01 0.729795597458E+01 0.000000000000E+00
52 0.310000000000E-01 0.759385537159E+01 0.000000000000E+00
53 0.320000000000E-01 0.788540837030E+01 0.000000000000E+00
54 0.330000000000E-01 0.817226834232E+01 0.000000000000E+00
55 0.340000000000E-01 0.845411989252E+01 0.000000000000E+00
56 0.350000000000E-01 0.873067709677E+01 0.000000000000E+00
57 0.360000000000E-01 0.900168202993E+01 0.000000000000E+00
58 0.370000000000E-01 0.926690314354E+01 0.000000000000E+00
59 0.380000000000E-01 0.952613393144E+01 0.000000000000E+00
60 0.390000000000E-01 0.977919143729E+01 0.000000000000E+00
61 0.400000000000E-01 0.100259150466E+02 0.000000000000E+00
62 0.410000000000E-01 0.102661651144E+02 0.000000000000E+00
63 0.420000000000E-01 0.104998218739E+02 0.000000000000E+00
64 0.430000000000E-01 0.107267841749E+02 0.000000000000E+00
65 0.440000000000E-01 0.109469684991E+02 0.000000000000E+00
66 0.450000000000E-01 0.111603078023E+02 0.000000000000E+00
67 0.460000000000E-01 0.113667506265E+02 0.000000000000E+00
68 0.470000000000E-01 0.115662600379E+02 0.000000000000E+00
69 0.480000000000E-01 0.117588128282E+02 0.000000000000E+00
70 0.490000000000E-01 0.119443985413E+02 0.000000000000E+00
71 0.500000000000E-01 0.121230187558E+02 0.000000000000E+00
72 0.510000000000E-01 0.122946861934E+02 0.000000000000E+00
73 0.520000000000E-01 0.124594240762E+02 0.000000000000E+00
74 0.530000000000E-01 0.126172653109E+02 0.000000000000E+00
75 0.540000000000E-01 0.127682519135E+02 0.000000000000E+00
76 0.550000000000E-01 0.129124342637E+02 0.000000000000E+00
77 0.560000000000E-01 0.130498705915E+02 0.000000000000E+00
78 0.570000000000E-01 0.131806262959E+02 0.000000000000E+00
79 0.580000000000E-01 0.133047734887E+02 0.000000000000E+00
80 0.590000000000E-01 0.134223903716E+02 0.000000000000E+00
81 0.600000000000E-01 0.135335608332E+02 0.000000000000E+00
82 0.620000000000E-01 0.137369231858E+02 0.000000000000E+00
83 0.640000000000E-01 0.139156271828E+02 0.000000000000E+00
84 0.660000000000E-01 0.140705011276E+02 0.000000000000E+00
85 0.680000000000E-01 0.142024242737E+02 0.000000000000E+00
86 0.700000000000E-01 0.143123149024E+02 0.000000000000E+00
87 0.720000000000E-01 0.144011220159E+02 0.000000000000E+00
88 0.740000000000E-01 0.144698156068E+02 0.000000000000E+00
89 0.760000000000E-01 0.145193802486E+02 0.000000000000E+00
90 0.780000000000E-01 0.145508072765E+02 0.000000000000E+00
91 0.800000000000E-01 0.145650899292E+02 0.000000000000E+00
92 0.820000000000E-01 0.145632171303E+02 0.000000000000E+00
93 0.840000000000E-01 0.145461698998E+02 0.000000000000E+00
94 0.860000000000E-01 0.145149164697E+02 0.000000000000E+00
95 0.880000000000E-01 0.144704097293E+02 0.000000000000E+00
96 0.900000000000E-01 0.144135834483E+02 0.000000000000E+00
97 0.920000000000E-01 0.143453505597E+02 0.000000000000E+00
98 0.940000000000E-01 0.142666002980E+02 0.000000000000E+00
99 0.960000000000E-01 0.141781971550E+02 0.000000000000E+00
100 0.980000000000E-01 0.140809787718E+02 0.000000000000E+00
101 0.100000000000E+00 0.139757554301E+02 0.000000000000E+00
102 0.102000000000E+00 0.138633085605E+02 0.000000000000E+00
103 0.104000000000E+00 0.137443906570E+02 0.000000000000E+00
104 0.106000000000E+00 0.136197242856E+02 0.000000000000E+00
105 0.108000000000E+00 0.134900023280E+02 0.000000000000E+00
106 0.110000000000E+00 0.133558873940E+02 0.000000000000E+00
107 0.112000000000E+00 0.132180123169E+02 0.000000000000E+00
108 0.114000000000E+00 0.130769798879E+02 0.000000000000E+00
109 0.116000000000E+00 0.129333635406E+02 0.000000000000E+00
110 0.118000000000E+00 0.127877073393E+02 0.000000000000E+00
111 0.120000000000E+00 0.126405268000E+02 0.000000000000E+00
112 0.122000000000E+00 0.124923090764E+02 0.000000000000E+00
113 0.124000000000E+00 0.123435138760E+02 0.000000000000E+00
114 0.126000000000E+00 0.121945737962E+02 0.000000000000E+00
115 0.128000000000E+00 0.120458953010E+02 0.000000000000E+00
116 0.130000000000E+00 0.118978591688E+02 0.000000000000E+00
117 0.132000000000E+00 0.117508215028E+02 0.000000000000E+00
118 0.134000000000E+00 0.116051142588E+02 0.000000000000E+00
119 0.136000000000E+00 0.114610462665E+02 0.000000000000E+00
120 0.138000000000E+00 0.113189038105E+02 0.000000000000E+00
121 0.140000000000E+00 0.111789516517E+02 0.000000000000E+00
122 0.144000000000E+00 0.109065733402E+02 0.000000000000E+00
123 0.148000000000E+00 0.106456277689E+02 0.000000000000E+00
124 0.152000000000E+00 0.103975360123E+02 0.000000000000E+00
125 0.156000000000E+00 0.101634506611E+02 0.000000000000E+00
126 0.160000000000E+00 0.994427827634E+01 0.000000000000E+00
127 0.164000000000E+00 0.974070118733E+01 0.000000000000E+00
128 0.168000000000E+00 0.955320856633E+01 0.000000000000E+00
129 0.172000000000E+00 0.938210818041E+01 0.000000000000E+00
130 0.176000000000E+00 0.922754822873E+01 0.000000000000E+00
131 0.180000000000E+00 0.908953714697E+01 0.000000000000E+00
132 0.184000000000E+00 0.896795938169E+01 0.000000000000E+00
133 0.188000000000E+00 0.886259238863E+01 0.000000000000E+00
134 0.192000000000E+00 0.877312004143E+01 0.000000000000E+00
135 0.196000000000E+00 0.869914699278E+01 0.000000000000E+00
136 0.200000000000E+00 0.864020983888E+01 0.000000000000E+00
137 0.204000000000E+00 0.859578907906E+01 0.000000000000E+00
138 0.208000000000E+00 0.856531822751E+01 0.000000000000E+00
139 0.212000000000E+00 0.854819364215E+01 0.000000000000E+00
140 0.216000000000E+00 0.854378181368E+01 0.000000000000E+00
141 0.220000000000E+00 0.855142734840E+01 0.000000000000E+00
142 0.224000000000E+00 0.857045868213E+01 0.000000000000E+00
143 0.228000000000E+00 0.860019450042E+01 0.000000000000E+00
144 0.232000000000E+00 0.863994812524E+01 0.000000000000E+00
145 0.236000000000E+00 0.868903264105E+01 0.000000000000E+00
146 0.240000000000E+00 0.874676418673E+01 0.000000000000E+00
147 0.244000000000E+00 0.881246602644E+01 0.000000000000E+00
148 0.248000000000E+00 0.888547094821E+01 0.000000000000E+00
149 0.252000000000E+00 0.896512447677E+01 0.000000000000E+00
150 0.256000000000E+00 0.905078653868E+01 0.000000000000E+00
151 0.260000000000E+00 0.914183396801E+01 0.000000000000E+00
152 0.264000000000E+00 0.923766155756E+01 0.000000000000E+00
153 0.268000000000E+00 0.933768397142E+01 0.000000000000E+00
154 0.272000000000E+00 0.944133627734E+01 0.000000000000E+00
155 0.276000000000E+00 0.954807536204E+01 0.000000000000E+00
156 0.280000000000E+00 0.965738003028E+01 0.000000000000E+00
157 0.284000000000E+00 0.976875200893E+01 0.000000000000E+00
158 0.288000000000E+00 0.988171569009E+01 0.000000000000E+00
159 0.292000000000E+00 0.999581879582E+01 0.000000000000E+00
160 0.296000000000E+00 0.101106318394E+02 0.000000000000E+00
161 0.300000000000E+00 0.102257485032E+02 0.000000000000E+00
162 0.308000000000E+00 0.104553787146E+02 0.000000000000E+00
163 0.316000000000E+00 0.106819076813E+02 0.000000000000E+00
164 0.324000000000E+00 0.109028727525E+02 0.000000000000E+00
165 0.332000000000E+00 0.111161395682E+02 0.000000000000E+00
166 0.340000000000E+00 0.113198756191E+02 0.000000000000E+00
167 0.348000000000E+00 0.115125374106E+02 0.000000000000E+00
168 0.356000000000E+00 0.116928409854E+02 0.000000000000E+00
169 0.364000000000E+00 0.118597484360E+02 0.000000000000E+00
170 0.372000000000E+00 0.120124387908E+02 0.000000000000E+00
171 0.380000000000E+00 0.121502951670E+02 0.000000000000E+00
172 0.388000000000E+00 0.122728772544E+02 0.000000000000E+00
173 0.396000000000E+00 0.123799099143E+02 0.000000000000E+00
174 0.404000000000E+00 0.124712579462E+02 0.000000000000E+00
175 0.412000000000E+00 0.125469165365E+02 0.000000000000E+00
176 0.420000000000E+00 0.126069886327E+02 0.000000000000E+00
177 0.428000000000E+00 0.126516773497E+02 0.000000000000E+00
178 0.436000000000E+00 0.126812660217E+02 0.000000000000E+00
179 0.444000000000E+00 0.126961124851E+02 0.000000000000E+00
180 0.452000000000E+00 0.126966317145E+02 0.000000000000E+00
181 0.460000000000E+00 0.126832917988E+02 0.000000000000E+00
182 0.468000000000E+00 0.126565989792E+02 0.000000000000E+00
183 0.476000000000E+00 0.126170950873E+02 0.000000000000E+00
184 0.484000000000E+00 0.125653447612E+02 0.000000000000E+00
185 0.492000000000E+00 0.125019341037E+02 0.000000000000E+00
186 0.500000000000E+00 0.124274598383E+02 0.000000000000E+00
187 0.508000000000E+00 0.123425289558E+02 0.000000000000E+00
188 0.516000000000E+00 0.122477495743E+02 0.000000000000E+00
189 0.524000000000E+00 0.121437313636E+02 0.000000000000E+00
190 0.532000000000E+00 0.120310778864E+02 0.000000000000E+00
191 0.540000000000E+00 0.119103876158E+02 0.000000000000E+00
192 0.548000000000E+00 0.117822475537E+02 0.000000000000E+00
193 0.556000000000E+00 0.116472346836E+02 0.000000000000E+00
194 0.564000000000E+00 0.115059106819E+02 0.000000000000E+00
195 0.572000000000E+00 0.113588236758E+02 0.000000000000E+00
196 0.580000000000E+00 0.112065038847E+02 0.000000000000E+00
197 0.588000000000E+00 0.110494655756E+02 0.000000000000E+00
198 0.596000000000E+00 0.108882034917E+02 0.000000000000E+00
199 0.604000000000E+00 0.107231949218E+02 0.000000000000E+00
200 0.612000000000E+00 0.105548967853E+02 0.000000000000E+00
201 0.620000000000E+00 0.103837477718E+02 0.000000000000E+00
202 0.636000000000E+00 0.100345496045E+02 0.000000000000E+00
203 0.652000000000E+00 0.967872344891E+01 0.000000000000E+00
204 0.668000000000E+00 0.931907101425E+01 0.000000000000E+00
205 0.684000000000E+00 0.895810820401E+01 0.000000000000E+00
206 0.700000000000E+00 0.859805485680E+01 0.000000000000E+00
207 0.716000000000E+00 0.824087119330E+01 0.000000000000E+00
208 0.732000000000E+00 0.788825582818E+01 0.000000000000E+00
209 0.748000000000E+00 0.754167995457E+01 0.000000000000E+00
210 0.764000000000E+00 0.720239080394E+01 0.000000000000E+00
211 0.780000000000E+00 0.687144226797E+01 0.000000000000E+00
212 0.796000000000E+00 0.654970128574E+01 0.000000000000E+00
213 0.812000000000E+00 0.623787449324E+01 0.000000000000E+00
214 0.828000000000E+00 0.593651588253E+01 0.000000000000E+00
215 0.844000000000E+00 0.564604949937E+01 0.000000000000E+00
216 0.860000000000E+00 0.536677735057E+01 0.000000000000E+00
217 0.876000000000E+00 0.509889842178E+01 0.000000000000E+00
218 0.892000000000E+00 0.484251621275E+01 0.000000000000E+00
219 0.908000000000E+00 0.459765446156E+01 0.000000000000E+00
220 0.924000000000E+00 0.436426397342E+01 0.000000000000E+00
221 0.940000000000E+00 0.414223547405E+01 0.000000000000E+00
222 0.956000000000E+00 0.393140557927E+01 0.000000000000E+00
223 0.972000000000E+00 0.373156719441E+01 0.000000000000E+00
224 0.988000000000E+00 0.354247458632E+01 0.000000000000E+00
225 0.100400000000E+01 0.336385171559E+01 0.000000000000E+00
226 0.102000000000E+01 0.319539644101E+01 0.000000000000E+00
227 0.103600000000E+01 0.303678712977E+01 0.000000000000E+00
228 0.105200000000E+01 0.288768606201E+01 0.000000000000E+00
229 0.106800000000E+01 0.274774461904E+01 0.000000000000E+00
230 0.108400000000E+01 0.261660597359E+01 0.000000000000E+00
231 0.110000000000E+01 0.249390911171E+01 0.000000000000E+00
232 0.111600000000E+01 0.237929089981E+01 0.000000000000E+00
233 0.113200000000E+01 0.227238915565E+01 0.000000000000E+00
234 0.114800000000E+01 0.217284418122E+01 0.000000000000E+00
235 0.116400000000E+01 0.208030106234E+01 0.000000000000E+00
236 0.118000000000E+01 0.199441075044E+01 0.000000000000E+00
237 0.119600000000E+01 0.191483173901E+01 0.000000000000E+00
238 0.121200000000E+01 0.184123076936E+01 0.000000000000E+00
239 0.122800000000E+01 0.177328400445E+01 0.000000000000E+00
240 0.124400000000E+01 0.171067742461E+01 0.000000000000E+00
241 0.126000000000E+01 0.165310759694E+01 0.000000000000E+00
242 0.129200000000E+01 0.155191724116E+01 0.000000000000E+00
243 0.132400000000E+01 0.146750525512E+01 0.000000000000E+00
244 0.135600000000E+01 0.139784381401E+01 0.000000000000E+00
245 0.138800000000E+01 0.134107966092E+01 0.000000000000E+00
246 0.142000000000E+01 0.129552654599E+01 0.000000000000E+00
247 0.145200000000E+01 0.125965628032E+01 0.000000000000E+00
248 0.148400000000E+01 0.123208593666E+01 0.000000000000E+00
249 0.151600000000E+01 0.121156835897E+01 0.000000000000E+00
250 0.154800000000E+01 0.119698112083E+01 0.000000000000E+00
251 0.158000000000E+01 0.118731944043E+01 0.000000000000E+00
252 0.161200000000E+01 0.118168771367E+01 0.000000000000E+00
253 0.164400000000E+01 0.117929367566E+01 0.000000000000E+00
254 0.167600000000E+01 0.117944032275E+01 0.000000000000E+00
255 0.170800000000E+01 0.118151949160E+01 0.000000000000E+00
256 0.174000000000E+01 0.118500323242E+01 0.000000000000E+00
257 0.177200000000E+01 0.118943698637E+01 0.000000000000E+00
258 0.180400000000E+01 0.119443119513E+01 0.000000000000E+00
259 0.183600000000E+01 0.119965506433E+01 0.000000000000E+00
260 0.186800000000E+01 0.120482918576E+01 0.000000000000E+00
261 0.190000000000E+01 0.120972037857E+01 0.000000000000E+00
262 0.193200000000E+01 0.121413551639E+01 0.000000000000E+00
263 0.196400000000E+01 0.121791745169E+01 0.000000000000E+00
264 0.199600000000E+01 0.122093993025E+01 0.000000000000E+00
265 0.202800000000E+01 0.122310443309E+01 0.000000000000E+00
266 0.206000000000E+01 0.122433599445E+01 0.000000000000E+00
267 0.209200000000E+01 0.122458078315E+01 0.000000000000E+00
268 0.212400000000E+01 0.122380265919E+01 0.000000000000E+00
269 0.215600000000E+01 0.122198134504E+01 0.000000000000E+00
270 0.218800000000E+01 0.121910958787E+01 0.000000000000E+00
271 0.222000000000E+01 0.121519180101E+01 0.000000000000E+00
272 0.225200000000E+01 0.121024172586E+01 0.000000000000E+00
273 0.228400000000E+01 0.120428144770E+01 0.000000000000E+00
274 0.231600000000E+01 0.119733947184E+01 0.000000000000E+00
275 0.234800000000E+01 0.118945003633E+01 0.000000000000E+00
276 0.238000000000E+01 0.118065153236E+01 0.000000000000E+00
277 0.241200000000E+01 0.117098605097E+01 0.000000000000E+00
278 0.244400000000E+01 0.116049808940E+01 0.000000000000E+00
279 0.247600000000E+01 0.114923428069E+01 0.000000000000E+00
280 0.250800000000E+01 0.113724233640E+01 0.000000000000E+00
281 0.254000000000E+01 0.112457091994E+01 0.000000000000E+00
282 0.260400000000E+01 0.109738470182E+01 0.000000000000E+00
283 0.266800000000E+01 0.106806439154E+01 0.000000000000E+00
284 0.273200000000E+01 0.103698439917E+01 0.000000000000E+00
285 0.279600000000E+01 0.100450307329E+01 0.000000000000E+00
286 0.286000000000E+01 0.970953381730E+00 0.000000000000E+00
287 0.292400000000E+01 0.936644159167E+00 0.000000000000E+00
288 0.298800000000E+01 0.901855019638E+00 0.000000000000E+00
289 0.305200000000E+01 0.866839215964E+00 0.000000000000E+00
290 0.311600000000E+01 0.831821125455E+00 0.000000000000E+00
291 0.318000000000E+01 0.796999736132E+00 0.000000000000E+00
292 0.324400000000E+01 0.762547673700E+00 0.000000000000E+00
293 0.330800000000E+01 0.728614749752E+00 0.000000000000E+00
294 0.337200000000E+01 0.695327865933E+00 0.000000000000E+00
295 0.343600000000E+01 0.662794304433E+00 0.000000000000E+00
296 0.350000000000E+01 0.631102113379E+00 0.000000000000E+00
297 0.356400000000E+01 0.600323008499E+00 0.000000000000E+00
298 0.362800000000E+01 0.570512981599E+00 0.000000000000E+00
299 0.369200000000E+01 0.541714781818E+00 0.000000000000E+00
300 0.375600000000E+01 0.513958604532E+00 0.000000000000E+00
301 0.382000000000E+01 0.487264171106E+00 0.000000000000E+00
302 0.388400000000E+01 0.461641419373E+00 0.000000000000E+00
303 0.394800000000E+01 0.437092224312E+00 0.000000000000E+00
304 0.401200000000E+01 0.413611047722E+00 0.000000000000E+00
305 0.407600000000E+01 0.391186347874E+00 0.000000000000E+00
306 0.414000000000E+01 0.369801165599E+00 0.000000000000E+00
307 0.420400000000E+01 0.349434267039E+00 0.000000000000E+00
308 0.426800000000E+01 0.330060656641E+00 0.000000000000E+00
309 0.433200000000E+01 0.311652491038E+00 0.000000000000E+00
310 0.439600000000E+01 0.294179509305E+00 0.000000000000E+00
311 0.446000000000E+01 0.277609755909E+00 0.000000000000E+00
312 0.452400000000E+01 0.261909928620E+00 0.000000000000E+00
313 0.458800000000E+01 0.247045937393E+00 0.000000000000E+00
314 0.465200000000E+01 0.232983174510E+00 0.000000000000E+00
315 0.471600000000E+01 0.219686935923E+00 0.000000000000E+00
316 0.478000000000E+01 0.207122620601E+00 0.000000000000E+00
317 0.484400000000E+01 0.195256038533E+00 0.000000000000E+00
318 0.490800000000E+01 0.184053548124E+00 0.000000000000E+00
319 0.497200000000E+01 0.173482273608E+00 0.000000000000E+00
320 0.503600000000E+01 0.163510189161E+00 0.000000000000E+00
321 0.510000000000E+01 0.154106267371E+00 0.000000000000E+00
322 0.522800000000E+01 0.136884591654E+00 0.000000000000E+00
323 0.535600000000E+01 0.121591321367E+00 0.000000000000E+00
324 0.548400000000E+01 0.108017651918E+00 0.000000000000E+00
325 0.561200000000E+01 0.959753749055E-01 0.000000000000E+00
326 0.574000000000E+01 0.852944707494E-01 0.000000000000E+00
327 0.586800000000E+01 0.758227542149E-01 0.000000000000E+00
328 0.599600000000E+01 0.674244363565E-01 0.000000000000E+00
329 0.612400000000E+01 0.599788218697E-01 0.000000000000E+00
330 0.625200000000E+01 0.533786398769E-01 0.000000000000E+00
331 0.638000000000E+01 0.475284971489E-01 0.000000000000E+00
332 0.650800000000E+01 0.423433479881E-01 0.000000000000E+00
333 0.663600000000E+01 0.377472637261E-01 0.000000000000E+00
334 0.676400000000E+01 0.336723948963E-01 0.000000000000E+00
335 0.689200000000E+01 0.300581838419E-01 0.000000000000E+00
336 0.702000000000E+01 0.268506826101E-01 0.000000000000E+00
337 0.714800000000E+01 0.240019738064E-01 0.000000000000E+00
338 0.727600000000E+01 0.214696134695E-01 0.000000000000E+00
339 0.740400000000E+01 0.192161145818E-01 0.000000000000E+00
340 0.753200000000E+01 0.172084431025E-01 0.000000000000E+00
341 0.766000000000E+01 0.154175504525E-01 0.000000000000E+00
342 0.778800000000E+01 0.138179319918E-01 0.000000000000E+00
343 0.791600000000E+01 0.123872273736E-01 0.000000000000E+00
344 0.804400000000E+01 0.111058555610E-01 0.000000000000E+00
345 0.817200000000E+01 0.995669175697E-02 0.000000000000E+00
346 0.830000000000E+01 0.892477900357E-02 0.000000000000E+00
347 0.842800000000E+01 0.799707541516E-02 0.000000000000E+00
348 0.855600000000E+01 0.716222883183E-02 0.000000000000E+00
349 0.868400000000E+01 0.641037533463E-02 0.000000000000E+00
350 0.881200000000E+01 0.573295290543E-02 0.000000000000E+00
351 0.894000000000E+01 0.512252596993E-02 0.000000000000E+00
352 0.906800000000E+01 0.457261653329E-02 0.000000000000E+00
353 0.919600000000E+01 0.407754389913E-02 0.000000000000E+00
354 0.932400000000E+01 0.363227714481E-02 0.000000000000E+00
355 0.945200000000E+01 0.323230745826E-02 0.000000000000E+00
356 0.958000000000E+01 0.287354503590E-02 0.000000000000E+00
357 0.970800000000E+01 0.255224239652E-02 0.000000000000E+00
358 0.983600000000E+01 0.226494165840E-02 0.000000000000E+00
359 0.996400000000E+01 0.200844067852E-02 0.000000000000E+00
360 0.100920000000E+02 0.177977305756E-02 0.000000000000E+00
361 0.102200000000E+02 0.157619451435E-02 0.000000000000E+00
362 0.104760000000E+02 0.123436917698E-02 0.000000000000E+00
363 0.107320000000E+02 0.965186451268E-03 0.000000000000E+00
364 0.109880000000E+02 0.753908554242E-03 0.000000000000E+00
365 0.112440000000E+02 0.588465538491E-03 0.000000000000E+00
366 0.115000000000E+02 0.459129900109E-03 0.000000000000E+00
367 0.117560000000E+02 0.358136490652E-03 0.000000000000E+00
368 0.120120000000E+02 0.279333173696E-03 0.000000000000E+00
369 0.122680000000E+02 0.217872128786E-03 0.000000000000E+00
370 0.125240000000E+02 0.169948253475E-03 0.000000000000E+00
371 0.127800000000E+02 0.132583106199E-03 0.000000000000E+00
372 0.130360000000E+02 0.103449732933E-03 0.000000000000E+00
373 0.132920000000E+02 0.807324659074E-04 0.000000000000E+00
374 0.135480000000E+02 0.630157231199E-04 0.000000000000E+00
375 0.138040000000E+02 0.491963718127E-04 0.000000000000E+00
376 0.140600000000E+02 0.384149672470E-04 0.000000000000E+00
377 0.143160000000E+02 0.300019668906E-04 0.000000000000E+00
378 0.145720000000E+02 0.234357449754E-04 0.000000000000E+00
379 0.148280000000E+02 0.183098631066E-04 0.000000000000E+00
380 0.150840000000E+02 0.143075777290E-04 0.000000000000E+00
381 0.153400000000E+02 0.111819939178E-04 0.000000000000E+00
382 0.155960000000E+02 0.874061827897E-05 0.000000000000E+00
383 0.158520000000E+02 0.683333638838E-05 0.000000000000E+00
384 0.161080000000E+02 0.534305478230E-05 0.000000000000E+00
385 0.163640000000E+02 0.417841576076E-05 0.000000000000E+00
386 0.166200000000E+02 0.326812462090E-05 0.000000000000E+00
387 0.168760000000E+02 0.255653132983E-05 0.000000000000E+00
388 0.171320000000E+02 0.200018830515E-05 0.000000000000E+00
389 0.173880000000E+02 0.156516791554E-05 0.000000000000E+00
390 0.176440000000E+02 0.122497144447E-05 0.000000000000E+00
391 0.179000000000E+02 0.958898661647E-06 0.000000000000E+00
392 0.181560000000E+02 0.750776203914E-06 0.000000000000E+00
393 0.184120000000E+02 0.587965550136E-06 0.000000000000E+00
394 0.186680000000E+02 0.460588927040E-06 0.000000000000E+00
395 0.189240000000E+02 0.360925130814E-06 0.000000000000E+00
396 0.191800000000E+02 0.282937864443E-06 0.000000000000E+00
397 0.194360000000E+02 0.221907449552E-06 0.000000000000E+00
398 0.196920000000E+02 0.174143200666E-06 0.000000000000E+00
399 0.199480000000E+02 0.136758752860E-06 0.000000000000E+00
400 0.202040000000E+02 0.107496536977E-06 0.000000000000E+00
401 0.204600000000E+02 0.845906225812E-07 0.000000000000E+00
diff --git a/src/labat/atomlab.cc b/src/labat/atomlab.cc
new file mode 100644
index 0000000..504a0d9
--- /dev/null
+++ b/src/labat/atomlab.cc
@@ -0,0 +1,187 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/config.h>
21#include <fstream>
22#include <iostream>
23#include <unistd.h>
24#include <fcntl.h>
25#include <signal.h>
26#include <sys/stat.h>
27using namespace std;
28
29const mstring LABAT=htchome()+sref("/bin/labat");
30
31const int SLOTS=8;
32const int RUNLIMIT=600;
33static int SLOT;
34
35extern "C" {
36static void FreeSlot(int dummy)
37{
38 static int ok=0;
39 static char buf[256];
40 if(!ok) {
41 ok=1;
42 sprintf(buf,"rm -rf /tmp/labat%d/",SLOT);
43 system(buf);
44 }
45}
46}
47
48static int AllocSlot()
49{
50 struct stat FS;
51 char buf[256];
52 for(SLOT=0;SLOT<SLOTS;SLOT++) {
53 sprintf(buf,"/tmp/labat%d/",SLOT);
54 if(stat(buf,&FS)!=0) {
55 signal(SIGTERM,FreeSlot);
56 signal(SIGINT,FreeSlot);
57 signal(SIGPIPE,FreeSlot);
58 sprintf(buf,"mkdir /tmp/labat%d/",SLOT);
59 system(buf);
60 return 1;
61 }
62 }
63 return 0;
64}
65
66///////////////////////////////////////////////////////////////////////////////
67
68struct CTLBasis {
69 int n,l,occ;
70 float e;
71 void SetEnergy(int Z) {
72 e=-0.5*float(Z*Z)/float(0.1+n*n*n+l*(l+1)*(l+2));
73 }
74};
75
76struct CTLData {
77 int atomz,its,basisn,exc;
78 float mix;
79 CTLBasis left[24],right[24];
80};
81
82static ostream& operator<<(ostream& out,const CTLData& ctl)
83{
84 out<<ctl.atomz<<" "<<0<<"\n";
85 out<<10<<" "<<40<<" "<<0.2<<"\n"; // Hermann-Skillman mesh
86 out<<ctl.mix<<" 0.00001 0.005\n"; // mix,error,?
87 out<<ctl.its<<" "<<0<<" "<<1<<" "<<0<<"\n"; // its ? step ?
88 out<<ctl.basisn<<" "<<2<<" "<<ctl.exc<<"\n"; // exc (C-A, B-H, GGA)
89 for(int i=0;i<ctl.basisn;i++) {
90 out<<ctl.left[i].n<<ctl.left[i].l<<0<<" "<<ctl.left[i].e
91 <<" "<<ctl.left[i].occ<<" "<<1<<" "<<0<<"\n";
92 }
93 for(int i=0;i<ctl.basisn;i++) {
94 out<<ctl.right[i].n<<ctl.right[i].l<<0<<" "<<ctl.right[i].e
95 <<" "<<ctl.right[i].occ<<" "<<1<<" "<<0<<"\n";
96 }
97 return out;
98}
99
100static void SetupLabat(mstring& resfile,int argc,char* argv[])
101{
102 CTLData ctl;
103 ctl.atomz=atoi(argv[1]);
104 ctl.its=atoi(argv[2]);
105 ctl.exc=atoi(argv[3]);
106 ctl.mix=atof(argv[4]);
107 resfile=argv[5];
108 ctl.basisn=0;
109 int nl,nr,elecs=0;
110 for(int i=0;i<6;i++) {
111 for(int k=0;k<3;k++) {
112 nl=int(argv[6+i][2*k]-'0');
113 nr=int(argv[6+i][2*k+1]-'0');
114 if(nl>0||nr>0) {
115 ctl.left[ctl.basisn].n=i+1;
116 ctl.left[ctl.basisn].l=k;
117 ctl.left[ctl.basisn].occ=nl;
118 ctl.left[ctl.basisn].SetEnergy(ctl.atomz);
119 ctl.right[ctl.basisn].n=i+1;
120 ctl.right[ctl.basisn].l=k;
121 ctl.right[ctl.basisn].occ=nr;
122 ctl.right[ctl.basisn].SetEnergy(ctl.atomz);
123 ctl.basisn++;
124 }
125 elecs+=nl+nr;
126 }
127 }
128 ctl.atomz+=elecs;
129 char buf[1024];
130 sprintf(buf,"/tmp/labat%d/atomctrl.dat",SLOT);
131 ofstream os(buf);
132 os<<ctl;
133 cout<<"Atomnumber: "<<ctl.atomz<<" Electrons: "<<elecs<<"<BR>\n";
134 cout<<"NOTE: if the program does >="<<ctl.its
135 <<" iterations, you must increase the number\n";
136 cout<<"of iterations and re-run, to assure convergence.<BR>\n";
137 cout<<"Also note that there is currently a maximum time limit of "<<
138 RUNLIMIT<<" seconds.<BR>\n";
139}
140
141static void RunLabat()
142{
143 char buf[1024];
144 sprintf(buf,"cd /tmp/labat%d/\nulimit -t %d\n%s",SLOT,RUNLIMIT,LABAT.c_str());
145 system(buf);
146}
147
148static void SaveLabat(const mstring& resfile)
149{
150 const char* docroot=getenv("DOCROOT");
151 if(docroot&&resfile.size()) {
152 char buf[1024];
153 sprintf(buf,"cp -rfp /tmp/labat%d/atomdens.dat %s/%s",
154 SLOT,docroot,resfile.c_str());
155 system(buf);
156 cout<<"<p>\n"
157 <<"Here you may download the density profile.\n"
158 <<"Example: Save the file as 'dens.dat', and load it from\n"
159 <<"matlab with 'load dens.dat'.\n"
160 <<"Then you can look at it with 'plot(dens(:,1),dens(:,2))'.\n"
161 <<"<p>\n"<<"<a href="<<resfile.c_str()<<">Get atomic density</a>\n";
162 }
163}
164
165main(int argc,char* argv[])
166{
167 if(argc<12) {
168 cerr<<"Usage: "<<argv[0]<<" <ion> <its> <exc> <mix> <resfile> <ssppdd>x6\n";
169 exit(-1);
170 }
171 mstring resfile;
172 char buf[1024];
173 if(AllocSlot()) {
174 cout<<"<h4>Running</h4>\n"
175 <<"<PRE>\n";
176 cout.flush();
177 SetupLabat(resfile,argc,argv);
178 RunLabat();
179 cout<<"</PRE>\n"
180 <<"<h4>Done</h4>\n";
181 SaveLabat(resfile);
182 FreeSlot(0);
183 }
184 else {
185 cout<<"No vacant slots at the moment. Try again later.\n";
186 }
187}
diff --git a/src/labat/deriv.f b/src/labat/deriv.f
new file mode 100644
index 0000000..b440070
--- /dev/null
+++ b/src/labat/deriv.f
@@ -0,0 +1,65 @@
1 function deriv(r,x,x2,spin,i,imin,imax)
2c deriv calculates the derivative of x with respect to r, at
3c position r(i).
4c input r : radial coordinate (array)
5c input x : function to be derivated (array)
6c input x2 : second derivative of x (array)
7c input spin : -1 if spin-down, 1 if spin-up, 0 otherwise
8c input i : counter, i.e. current position = r(i)
9c input imin : min value of i
10c input imax : max value of i
11 implicit logical (a-z)
12 double precision deriv,r,x,x2
13 double precision h,d,dforw,dback,dforup,dfordn,dbacup,dbacdn
14 integer spin,i,imin,imax
15 dimension r(561),x(2,561),x2(2,561)
16 if (i.eq.imin) then
17 h = (r(i+1)-r(i))/2.d0
18 if (spin.eq.-1) then
19 d = x(2,i)
20 call splint(r,x,x2,-1,imin,imax,r(i)+h,dforw)
21 elseif (spin.eq.1) then
22 d = x(1,i)
23 call splint(r,x,x2,1,imin,imax,r(i)+h,dforw)
24 else
25 d = (x(1,i) + x(2,i))
26 call splint(r,x,x2,1,imin,imax,r(i)+h,dforup)
27 call splint(r,x,x2,-1,imin,imax,r(i)+h,dfordn)
28 dforw = dforup + dfordn
29 endif
30 deriv = (dforw-d)/h
31 elseif (i.eq.imax) then
32 h = (r(i)-r(i-1))/2.d0
33 if (spin.eq.-1) then
34 call splint(r,x,x2,-1,imin,imax,r(i)-h,dback)
35 d = x(2,i)
36 elseif (spin.eq.1) then
37 call splint(r,x,x2,1,imin,imax,r(i)-h,dback)
38 d = x(1,i)
39 else
40 call splint(r,x,x2,1,imin,imax,r(i)-h,dbacup)
41 call splint(r,x,x2,-1,imin,imax,r(i)-h,dbacdn)
42 dback = dbacup + dbacdn
43 d = x(1,i) + x(2,i)
44 endif
45 deriv = (d-dback)/h
46 else
47 h = (r(i)-r(i-1))/2.d0
48 if (spin.eq.-1) then
49 call splint(r,x,x2,-1,imin,imax,r(i)+h,dforw)
50 call splint(r,x,x2,-1,imin,imax,r(i)-h,dback)
51 elseif (spin.eq.1) then
52 call splint(r,x,x2,1,imin,imax,r(i)+h,dforw)
53 call splint(r,x,x2,1,imin,imax,r(i)-h,dback)
54 else
55 call splint(r,x,x2,-1,imin,imax,r(i)+h,dfordn)
56 call splint(r,x,x2,-1,imin,imax,r(i)-h,dbacdn)
57 call splint(r,x,x2,1,imin,imax,r(i)+h,dforup)
58 call splint(r,x,x2,1,imin,imax,r(i)-h,dbacup)
59 dback = dbacup + dbacdn
60 dforw = dforup + dfordn
61 endif
62 deriv = (dforw-dback)/(2.d0*h)
63 endif
64 return
65 end
diff --git a/src/labat/exchen.f b/src/labat/exchen.f
new file mode 100644
index 0000000..a3d1112
--- /dev/null
+++ b/src/labat/exchen.f
@@ -0,0 +1,21 @@
1 subroutine exchen(d,s,ex)
2c gga91 exchange energy for a spin-unpolarized electronic system
3c input d : density
4c input s : abs(grad d)/(2*kf*d)
5c output ex : exchange energy per electron
6 implicit double precision (a-h,o-z)
7 data a1,a2,a3,a4/0.19645d0,0.27430d0,0.15084d0,100.d0/
8 data ax,a,b1/-0.7385588d0,7.7956d0,0.004d0/
9 data thrd/0.333333333333d0/
10 fac = ax*d**thrd
11 s2 = s*s
12 s4 = s2*s2
13 p0 = 1.d0/dsqrt(1.d0+a*a*s2)
14 p1 = dlog(a*s+1.d0/p0)
15 p2 = dexp(-a4*s2)
16 p3 = 1.d0/(1.d0+a1*s*p1+b1*s4)
17 p4 = 1.d0+a1*s*p1+(a2-a3*p2)*s2
18 f = p3*p4
19 ex = fac*f
20 return
21 end
diff --git a/src/labat/exchpt.f b/src/labat/exchpt.f
new file mode 100644
index 0000000..b44f49e
--- /dev/null
+++ b/src/labat/exchpt.f
@@ -0,0 +1,33 @@
1 subroutine exchpt(d,s,u,v,vx)
2c gga91 exchange potential for a spin-unpolarized electronic system
3c input d : density
4c input s : abs(grad d)/(2*kf*d)
5c input u : (grad d)*grad(abs(grad d))/(d**2 * (2*kf)**3)
6c input v : (laplacian d)/(d*(2*kf)**2)
7c output vx : exchange potential per electron
8 implicit double precision (a-h,o-z)
9 data a1,a2,a3,a4/0.19645d0,0.27430d0,0.15084d0,100.d0/
10 data ax,a,b1/-0.7385588d0,7.7956d0,0.004d0/
11 data thrd,thrd4/0.333333333333d0,1.33333333333d0/
12 fac = ax*d**thrd
13 s2 = s*s
14 s3 = s2*s
15 s4 = s2*s2
16 p0 = 1.d0/dsqrt(1.d0+a*a*s2)
17 p1 = dlog(a*s+1.d0/p0)
18 p2 = dexp(-a4*s2)
19 p3 = 1.d0/(1.d0+a1*s*p1+b1*s4)
20 p4 = 1.d0+a1*s*p1+(a2-a3*p2)*s2
21 f = p3*p4
22 p5 = b1*s2-(a2-a3*p2)
23 p6 = a1*s*(p1+a*s*p0)
24 p7 = 2.d0*(a2-a3*p2)+2.d0*a3*a4*s2*p2-4.d0*b1*s2*f
25 fs = p3*(p3*p5*p6+p7)
26 p8 = 2.d0*s*(b1-a3*a4*p2)
27 p9 = a1*p1+a*a1*s*p0*(3.d0-a*a*s2*p0*p0)
28 p10 = 4.d0*a3*a4*s*p2*(2.d0-a4*s2)-8.d0*b1*s*f-4.d0*b1*s3*fs
29 p11 = -p3*p3*(a1*p1+a*a1*s*p0+4.d0*b1*s3)
30 fss = p3*p3*(p5*p9+p6*p8)+2.d0*p3*p5*p6*p11+p3*p10+p7*p11
31 vx = fac*(thrd4*f-(u-thrd4*s3)*fss-v*fs)
32 return
33 end
diff --git a/src/labat/gcor.f b/src/labat/gcor.f
new file mode 100644
index 0000000..afdc739
--- /dev/null
+++ b/src/labat/gcor.f
@@ -0,0 +1,15 @@
1 subroutine gcor(a,a1,b1,b2,b3,b4,p,rs,gg,ggrs)
2c called by subroutines ldaec and ldauc
3 implicit double precision (a-h,o-z)
4 p1 = p + 1.d0
5 q0 = -2.d0*a*(1.d0+a1*rs)
6 rs12 = dsqrt(rs)
7 rs32 = rs12**3
8 rsp = rs**p
9 q1 = 2.d0*a*(b1*rs12+b2*rs+b3*rs32+b4*rs*rsp)
10 q2 = dlog(1.d0+1.d0/q1)
11 gg = q0*q2
12 q3 = a*(b1/rs12+2.d0*b2+3.d0*b3*rs12+2.d0*b4*p1*rsp)
13 ggrs = -2.d0*a*a1*q2-q0*q3/(q1**2+q1)
14 return
15 end
diff --git a/src/labat/gga.f b/src/labat/gga.f
new file mode 100644
index 0000000..083fdad
--- /dev/null
+++ b/src/labat/gga.f
@@ -0,0 +1,45 @@
1c*****************************************************************
2c*****************************************************************
3c*****************************************************************
4c GGA
5c The Generalized Gradient Approximation
6
7c GGA is a way to improve the local spin density approximation
8c by adding nonlocal gradients in the evaluation of the exchange-
9c correlation energy and potential. These functions and subroutines
10c are based on programs made by John Perdew, Tulane University,
11c New Orleans, Louisiana, USA. Email: PY03APF%music.tcs.tulane.edu
12c The modifications necessary to fit them to the atom program was
13c made by Tomas Holmquist 1993 (so now you know who to blame).
14c Email: tomash@fy.chalmers.se
15c A more thorough description of the GGA used may be found in
16c J.P. Perdew et al, Phys. Rev. B (46) 1992 pp. 6671-6687.
17
18c The GGA package is:
19
20c function deriv
21c subroutine grad
22c subroutine grabgr
23c subroutine laplac
24c subroutine spline
25c subroutine splint
26c subroutine ggaexc
27c subroutine exchen
28c subroutine ldaec
29c subroutine gcor
30c subroutine ggaec
31c subroutine ggauxc
32c subroutine exchpt
33c subroutine ldauc
34c subroutine ggauc
35
36c The grad, grabgr, and laplace subroutines uses the function deriv
37c to calculate different derivatives with respect to the radial
38c coordinate r. Spline and splint calculates the cubic spline
39c interpolation which is used in function deriv.
40c The two main subprograms, ggaexc and ggauxc, calculates
41c the exchange-correlation energy and potential respectively.
42c The other subroutines are modified versions of Perdew's program.
43
44c*****************************************************************
45c*****************************************************************
diff --git a/src/labat/ggaec.f b/src/labat/ggaec.f
new file mode 100644
index 0000000..3177859
--- /dev/null
+++ b/src/labat/ggaec.f
@@ -0,0 +1,43 @@
1 subroutine ggaec(rs,zet,t,ec,h)
2c called by subroutine ggaexc
3c gga91 correlation
4c input rs : seitz radius
5c input zet : relative spin polarization
6c input t : abs(grad d)/(d*2.*ks*g)
7c input : correlation energy per electron (ec)
8c output h : nonlocal part of correlation energy per electron
9 implicit double precision (a-h,o-z)
10 data xnu,cc0,cx,alf/15.75592d0,0.004235d0,-0.001667212d0,0.09d0/
11 data c1,c2,c3,c4/0.002568d0,0.023266d0,7.389d-6,8.723d0/
12 data c5,c6,a4/0.472d0,7.389d-2,100.d0/
13 data thrd2/0.666666666667d0/
14 pi = 4.d0*datan(1.d0)
15 fk = 1.91915829d0/rs
16 sk = dsqrt(4.d0*fk/pi)
17 g = ((1.d0+zet)**thrd2+(1.d0-zet)**thrd2)/2.d0
18 bet = xnu*cc0
19 delt = 2.d0*alf/bet
20 g3 = g**3
21 g4 = g3*g
22 pon = -delt*ec/(g3*bet)
23 b = delt/(dexp(pon)-1.d0)
24 b2 = b*b
25 t2 = t*t
26 t4 = t2*t2
27 rs2 = rs*rs
28 rs3 = rs2*rs
29 q4 = 1.d0+b*t2
30 q5 = 1.d0+b*t2+b2*t4
31 q6 = c1+c2*rs+c3*rs2
32 q7 = 1.d0+c4*rs+c5*rs2+c6*rs3
33 cc = -cx + q6/q7
34 r0 = (sk/fk)**2
35 r1 = a4*r0*g4
36 coeff = cc-cc0-3.d0*cx/7.d0
37 r2 = xnu*coeff*g3
38 r3 = dexp(-r1*t2)
39 h0 = g3*(bet/delt)*dlog(1.d0+delt*q4*t2/q5)
40 h1 = r3*r2*t2
41 h = h0 + h1
42 return
43 end
diff --git a/src/labat/ggaexc.f b/src/labat/ggaexc.f
new file mode 100644
index 0000000..135b42e
--- /dev/null
+++ b/src/labat/ggaexc.f
@@ -0,0 +1,76 @@
1 subroutine ggaexc(r,db,i,imin,imax,doned,exc)
2c ggaexc calculates the exchange-correlation energy
3c input r : position coordinate (array)
4c input db : spin up and down density. (array)
5c input i : counter, i.e. present position = r(i)
6c input imin : min value of i
7c input imax : max value of i
8c in/output doned : true if density is splined
9c output exc : exchange-correlation energy
10 implicit logical (a-z)
11 logical doned
12 double precision r,db,gradd,gradup,graddn,fk,fkup,fkdn,sk,g
13 double precision sup,sdn,t,exc,ec
14 double precision onethi,twothi,pi,conkf,d,zet,rs,exup,exdn
15 double precision ex,eclda,ecgga
16 integer i,imin,imax
17 dimension r(561),db(2,561)
18 dimension gradd(561),gradup(561),graddn(561),fk(561),fkup(561)
19 dimension fkdn(561),sk(561),g(561),sup(561),sdn(561),t(561)
20 common/gga/gradd,gradup,graddn,fkup,fkdn,sk,g,sup,sdn,t
21 onethi = 1.d0/3.d0
22 twothi = 2.d0/3.d0
23 pi = 4.d0*datan(1.d0)
24 conkf = (3.d0*pi**2)**onethi
25 d = db(1,i) + db(2,i)
26 call grad(r,db,i,imin,imax,doned,gradd(i),gradup(i),graddn(i))
27
28c calculate the exchange energy, first spin up, then spin down
29
30 if (db(1,i).gt.1.d-100) then
31 fkup(i) = conkf*(2.d0*db(1,i))**onethi
32 sup(i) = dabs(gradup(i))/(2.d0*fkup(i)*db(1,i))
33 call exchen(2.d0*db(1,i),sup(i),exup)
34 else
35 fkup(i) = 0.d0
36 sup(i) = 0.d0
37 exup = 0.d0
38 endif
39 if (db(2,i).gt.1.d-100) then
40 fkdn(i) = conkf*(2.d0*db(2,i))**onethi
41 sdn(i) = dabs(graddn(i))/(2.d0*fkdn(i)*db(2,i))
42 call exchen(2.d0*db(2,i),sdn(i),exdn)
43 else
44 fkdn(i) = 0.d0
45 sdn(i) = 0.d0
46 exdn = 0.d0
47 endif
48 if (d.gt.1d-100) then
49 ex = (exup*db(1,i) + exdn*db(2,i))/d
50 else
51 ex = 0.d0
52 endif
53
54c exchange energy done, now calculate the correlation energy
55
56 fk(i) = conkf*d**onethi
57 sk(i) = dsqrt(4.d0*fk(i)/pi)
58 if (d.gt.1.d-100) then
59 zet = (db(1,i) - db(2,i))/d
60 else
61 zet = 0.d0
62 endif
63 g(i) = ((1.d0+zet)**twothi+(1.d0-zet)**twothi)/2.d0
64 if (d.gt.1.d-18) then
65 rs = (3.d0/(4.d0*pi*d))**onethi
66 t(i) = dabs(gradd(i))/(d*2*sk(i)*g(i))
67 call ldaec(rs,zet,eclda)
68 call ggaec(rs,zet,t(i),eclda,ecgga)
69 ec = eclda + ecgga
70 else
71 ec = 0.d0
72 endif
73 exc = ex + ec
74
75 return
76 end
diff --git a/src/labat/ggauc.f b/src/labat/ggauc.f
new file mode 100644
index 0000000..f3adcf5
--- /dev/null
+++ b/src/labat/ggauc.f
@@ -0,0 +1,96 @@
1 subroutine ggauc(rs,zet,t,uu,vv,ww,ec,ecrs,eczet,dvcup,dvcdn)
2c gga91 correlation
3c input rs : seitz radius
4c input zet : relative spin polarization
5c input t : abs(grad d)/(d*2.*ks*g)
6c input uu : (grad d)*grad(abs(grad d))/(d**2 * (2*ks*g)**3)
7c input vv : (laplacian d)/(d * (2*ks*g)**2)
8c input ww : (grad d)*(grad zet)/(d * (2*ks*g)**2
9c input ec : correlation energy
10c input ecrs : derivative of ec with respect to rs
11c input eczet : derivative of ec with respect to zet
12c output dvcup,dvcdn : nonlocal parts of correlation potentials
13 implicit double precision (a-h,o-z)
14 data xnu,cc0,cx,alf/15.75592d0,0.004235d0,-0.001667212d0,0.09d0/
15 data c1,c2,c3,c4/0.002568d0,0.023266d0,7.389d-6,8.723d0/
16 data c5,c6,a4/0.472d0,7.389d-2,100.d0/
17 data thrdm,thrd2/-0.333333333333d0,0.666666666667d0/
18 pi = 4.d0*datan(1.d0)
19 fk = 1.91915829d0/rs
20 sk = dsqrt(4.d0*fk/pi)
21 g = ((1.d0+zet)**thrd2+(1.d0-zet)**thrd2)/2.d0
22 bet = xnu*cc0
23 delt = 2.d0*alf/bet
24 g3 = g**3
25 g4 = g3*g
26 pon = -delt*ec/(g3*bet)
27 b = delt/(dexp(pon)-1.d0)
28 b2 = b*b
29 t2 = t*t
30 t4 = t2*t2
31 t6 = t4*t2
32 rs2 = rs*rs
33 rs3 = rs2*rs
34 q4 = 1.d0+b*t2
35 q5 = 1.d0+b*t2+b2*t4
36 q6 = c1+c2*rs+c3*rs2
37 q7 = 1.d0+c4*rs+c5*rs2+c6*rs3
38 cc = -cx + q6/q7
39 r0 = (sk/fk)**2
40 r1 = a4*r0*g4
41 coeff = cc-cc0-3.d0*cx/7.d0
42 r2 = xnu*coeff*g3
43 r3 = dexp(-r1*t2)
44 h0 = g3*(bet/delt)*dlog(1.d0+delt*q4*t2/q5)
45 h1 = r3*r2*t2
46 h = h0+h1
47c energy done. now the potential:
48 ccrs = (c2+2.*c3*rs)/q7 - q6*(c4+2.*c5*rs+3.*c6*rs2)/q7**2
49 rsthrd = rs/3.d0
50 r4 = rsthrd*ccrs/coeff
51c=========================================================
52c fix made by Tomas Holmquist
53 if ((zet.eq.1.d0).or.(zet.eq.-1.d0)) then
54 gz = 0.d0
55 else
56 gz = ((1.d0+zet)**thrdm - (1.d0-zet)**thrdm)/3.d0
57 endif
58c=========================================================
59 fac = delt/b+1.d0
60 bg = -3.d0*b2*ec*fac/(bet*g4)
61 bec = b2*fac/(bet*g3)
62 q8 = q5*q5+delt*q4*q5*t2
63 q9 = 1.d0+2.d0*b*t2
64 h0b = -bet*g3*b*t6*(2.d0+b*t2)/q8
65 h0rs = -rsthrd*h0b*bec*ecrs
66 fact0 = 2.d0*delt-6.d0*b
67 fact1 = q5*q9+q4*q9*q9
68 h0bt = 2.d0*bet*g3*t4*((q4*q5*fact0-delt*fact1)/q8)/q8
69 h0rst = rsthrd*t2*h0bt*bec*ecrs
70 h0z = 3.d0*gz*h0/g + h0b*(bg*gz+bec*eczet)
71 h0t = 2.*bet*g3*q9/q8
72 h0zt = 3.d0*gz*h0t/g+h0bt*(bg*gz+bec*eczet)
73 fact2 = q4*q5+b*t2*(q4*q9+q5)
74 fact3 = 2.d0*b*q5*q9+delt*fact2
75 h0tt = 4.d0*bet*g3*t*(2.d0*b/q8-(q9*fact3/q8)/q8)
76 h1rs = r3*r2*t2*(-r4+r1*t2/3.d0)
77 fact4 = 2.d0-r1*t2
78 h1rst = r3*r2*t2*(2.d0*r4*(1.d0-r1*t2)-thrd2*r1*t2*fact4)
79 h1z = gz*r3*r2*t2*(3.d0-4.d0*r1*t2)/g
80 h1t = 2.d0*r3*r2*(1.d0-r1*t2)
81 h1zt = 2.d0*gz*r3*r2*(3.d0-11.d0*r1*t2+4.d0*r1*r1*t4)/g
82 h1tt = 4.d0*r3*r2*r1*t*(-2.d0+r1*t2)
83 hrs = h0rs+h1rs
84 hrst = h0rst+h1rst
85 ht = h0t+h1t
86 htt = h0tt+h1tt
87 hz = h0z+h1z
88 hzt = h0zt+h1zt
89 comm = h+hrs+hrst+t2*ht/6.d0+7.d0*t2*t*htt/6.d0
90 pref = hz-gz*t2*ht/g
91 fact5 = gz*(2.d0*ht+t*htt)/g
92 comm = comm-pref*zet-uu*htt-vv*ht-ww*(hzt-fact5)
93 dvcup = comm + pref
94 dvcdn = comm - pref
95 return
96 end
diff --git a/src/labat/ggauxc.f b/src/labat/ggauxc.f
new file mode 100644
index 0000000..d5fcb61
--- /dev/null
+++ b/src/labat/ggauxc.f
@@ -0,0 +1,82 @@
1 subroutine ggauxc(r,db,zet,i,imin,imax,donela,donegr,donez,
2 j uxcup,uxcdn)
3c ggauxc calculates the exchange-correlation potential by taking
4c the functional derivative of the energy with respect to the density
5c input r : position coordinate (array)
6c input db : spin up and down density. (array)
7c input zet : relative spin polarization (array)
8c input i : counter, i.e. present position = r(i)
9c input imin : min value of i
10c input imax : max value of i
11c in/output donela : true if r^2*grad(density) is splined
12c in/output donegr : true if abs(grad(density)) is splined
13c in/output donez : true if zet is splined
14c output uxcup : spin-up exchange-correlation potential
15c output uxcdn : spin-down exchange-correlation potential
16 implicit logical (a-z)
17 double precision r,db,zet,uxcup,uxcdn,gradd,gradup,graddn
18 double precision fkup,fkdn,sk,g,sup,sdn,t,tempz,z2,gradz
19 double precision onethi,pi,d,rs,lapld,laplup,lapldn,deriv
20 double precision gagd,gagup,gagdn,uu,vv,ww,uup,vup,udn,vdn
21 double precision uclcup,uclcdn,ucgaup,ucgadn,uxup,uxdn
22 double precision ucup,ucdn,ec,ecrs,eczet
23 integer i,imin,imax,j
24 logical donela,donegr,donez
25 common/gga/gradd,gradup,graddn,fkup,fkdn,sk,g,sup,sdn,t
26 common/ggaz/tempz,z2
27 dimension r(561),db(2,561),zet(561),tempz(2,561),z2(2,561)
28 dimension gradd(561),gradup(561),graddn(561),fkup(561)
29 dimension fkdn(561),sk(561),g(561),sup(561),sdn(561),t(561)
30 onethi = 1.d0/3.d0
31 pi = 4.d0*datan(1.d0)
32 call laplac(r,gradup,graddn,i,imin,imax,donela,lapld,laplup,
33 j lapldn)
34 call grabgr(r,gradup,graddn,i,imin,imax,donegr,gagd,gagup,gagdn)
35
36c calculate the exchange potential
37 if (db(1,i).gt.1.d-100) then
38 uup = gradup(i)*gagup/(db(1,i)**2*(2.d0*fkup(i))**3)
39 vup = laplup/(db(1,i)*(2.d0*fkup(i))**2)
40 call exchpt(2.d0*db(1,i),sup(i),uup,vup,uxup)
41 else
42 uxup = 0.d0
43 endif
44 if (db(2,i).gt.1.d-100) then
45 udn = graddn(i)*gagdn/(db(2,i)**2*(2.d0*fkdn(i))**3)
46 vdn = lapldn/(db(2,i)*(2.d0*fkdn(i))**2)
47 call exchpt(2.d0*db(2,i),sdn(i),udn,vdn,uxdn)
48 else
49 uxdn = 0.d0
50 endif
51
52c exchange potential done, now calculate the correlation potential
53
54 if (.not.donez) then
55 do 10 j = imin,imax
56 tempz(1,j) = zet(j)
57 10 continue
58 call spline(r,imin+1,imax,tempz,z2)
59 donez = .true.
60 endif
61 gradz = deriv(r,tempz,z2,1,i,imin,imax)
62 d = db(1,i) + db(2,i)
63 if (d.gt.1.d-18) then
64 rs = (3.d0/(4.d0*pi*d))**onethi
65 uu = gradd(i)*gagd/(d**2*(2.d0*sk(i)*g(i))**3)
66 vv = lapld/(d*(2.d0*sk(i)*g(i))**2)
67 ww = gradd(i)*gradz/(d*(2.d0*sk(i)*g(i))**2)
68 call ldauc(rs,zet(i),ec,ecrs,eczet,uclcup,uclcdn)
69 call ggauc(rs,zet(i),t(i),uu,vv,ww,ec,ecrs,eczet,ucgaup,
70 j ucgadn)
71 ucup = uclcup + ucgaup
72 ucdn = uclcdn + ucgadn
73 else
74 ucdn = 0.d0
75 ucup = 0.d0
76 endif
77 uxcup = uxup + ucup
78 uxcdn = uxdn + ucdn
79
80 return
81 end
82
diff --git a/src/labat/grabgr.f b/src/labat/grabgr.f
new file mode 100644
index 0000000..1ed039c
--- /dev/null
+++ b/src/labat/grabgr.f
@@ -0,0 +1,32 @@
1 subroutine grabgr(r,gradup,graddn,i,imin,imax,done,gagd,gagup,
2 j gagdn)
3c calculates grad(abs(grad(density)))
4c input r : radial coordinate (array)
5c input gradup : grad(density), spin up (array)
6c input graddn : grad(density), spin down (array)
7c input i : counter, i.e. current position = r(i)
8c input imin : min value of i
9c input imax : max value of i
10c in/output done : true if abs(grad(density)) is splined
11c output gagd : grad(abs(grad(density)))
12c output gagup,gagdn : grad(abs(grad(density))), spin up and down
13 implicit logical (a-z)
14 logical done
15 double precision r,gradup,graddn,gagd,gagup,gagdn,temp,gag2,deriv
16 integer i,imin,imax,j
17 common/ggagag/temp,gag2
18 dimension r(561),gradup(561),graddn(561)
19 dimension temp(2,561),gag2(2,561)
20 if (.not.done) then
21 do 10 j = imin,imax
22 temp(1,j) = dabs(gradup(j))
23 temp(2,j) = dabs(graddn(j))
24 10 continue
25 call spline(r,imin+1,imax,temp,gag2)
26 done = .true.
27 endif
28 gagup = deriv(r,temp,gag2,1,i,imin,imax)
29 gagdn = deriv(r,temp,gag2,-1,i,imin,imax)
30 gagd = gagup + gagdn
31 return
32 end
diff --git a/src/labat/grad.f b/src/labat/grad.f
new file mode 100644
index 0000000..845ed5a
--- /dev/null
+++ b/src/labat/grad.f
@@ -0,0 +1,26 @@
1 subroutine grad(r,db,i,imin,imax,done,gradd,gradup,graddn)
2c grad calculates the derivative of db with respect to r, at
3c position r(i).
4c input r : radial coordinate (array)
5c input db : spin-up and down densities (array)
6c input i : counter, i.e. current position = r(i)
7c input imin : min value of i
8c input imax : max value of i
9c in/output done : true if density is splined
10c output gradd : grad(density)
11c output gradup,graddn : grad(density), spin up and down
12 implicit logical (a-z)
13 logical done
14 double precision r,db,gradd,gradup,graddn,db2,deriv
15 integer i,imin,imax
16 dimension r(561),db(2,561),db2(2,561)
17 common/ggagra/db2
18 if (.not.done) then
19 call spline(r,imin+1,imax,db,db2)
20 done = .true.
21 endif
22 gradup = deriv(r,db,db2,1,i,imin,imax)
23 graddn = deriv(r,db,db2,-1,i,imin,imax)
24 gradd = gradup + graddn
25 return
26 end
diff --git a/src/labat/labat.f b/src/labat/labat.f
new file mode 100644
index 0000000..da1f7fe
--- /dev/null
+++ b/src/labat/labat.f
@@ -0,0 +1,587 @@
1 program atom
2 implicit double precision (a-h,o-z)
3 dimension dval(2,561),nval(2,7,10),ddval(2,561),ndval(2,7,10)
4 dimension dcore(2,561),vhv(561),fpu(561)
5c
6c free atom program by m.p. summer 1985 (valence energy and core
7c density are calculated)
8c
9c GGA implemented by T. Holmquist and U. Yxklinten.
10c
11c files used:
12c 6: terminal output
13c 22: density and potential output
14c 33: density and potential input
15c 44: potential and density double prec. output
16c 46: potential and density double prec. input
17c 55: control input
18c 66: printer output
19c 77: density (total and core) output (J.H.)
20c
21 dimension r(561),veff(2,561),vc(561),vcold(561),vv(561)
22 dimension gr(561),lm(2),rnocc(2,7,10),ux1(561),ux2(561)
23 dimension u(561),roo(561),spl(561),nb(7)
24 dimension db(2,561),v(561),vold(2,561)
25 dimension snlo(561),wj(301),ekin(2)
26 dimension ebound(2,7,10),nbound(2,7),de(2,7,10)
27 dimension apu(561),bpu(561),cpu(561),dpu(561),nlp(2,7,10)
28 dimension epu(561)
29c===================================================================
30c gga
31 dimension excgga(561),uxcup(561),uxcdn(561)
32 logical doned,donela,donegr,donez,donec
33c gga
34c===================================================================
35 common/sc/gr,r,snlo,nbl
36 common/mess/wj,dx,nblock,jblock
37 common/pot/v
38 frs(x)=(3.d0/(4.d0*pi*x))**(1.d0/3.d0)
39 pi=4.d0*datan(1.d0)
40 pi2=pi/2.d0
41 a=(4.d0/9.d0/pi)**(1.d0/3.d0)
42c
43 open(22,file='adensout.dat',status='unknown')
44 open(33,file='adensin.dat',status='unknown')
45 open(44,file='apotout.dat',status='unknown')
46 open(46,file='apotin.dat',status='unknown')
47 open(55,file='atomctrl.dat',status='old')
48 open(66,file='aprtout.dat',status='unknown')
49 open(77,file='atomdens.dat',status='unknown')
50 write(6,*) '=== Its ===== Energy (Ha) ======'
51 call flush(6)
52 read(55,*)z,zion
53c z : atomic number
54c zion : ionicity
55c
56 write(66,2) z,zion
572 format(/' atom number:',f5.0,' ionicity:',f5.0)
58 sf=4.d0*pi
59 read(55,*)jblock,nbl,c
60c parameters of the hermann-skillmann mesh
61 read(55,*)fback,thresh,qsc
62C fback : feedback
63c thresh : error allowed for the bound state eigenenergy
64c e.g. 0.00001
65c qsc : parameter for the screened green's function (0.005)
66 read(55,*)itmax,inopt,ipr,iout
67c itmax : max. no. of iterations
68c iopt : =0 starting potential generated; =1 starting potential
69c read in; =2 starting potential read in from unit 46.
70c (double precision format)
71c ipr, iout : print out parameters
72c
73c set up the herman-skillman mesh
74c
75 nblock=jblock
76 mesh=nblock*nbl+1
77 n=mesh
78 mest=mesh
79 dx=c*0.0025d0
80 en0=-0.01d0
81 i=1
82 r(i)=0.d0
83 deltax=dx
84 do 251 j=1,nblock
85 do 241 jk=1,nbl
86 i=i+1
87 241 r(i)=r(i-1)+deltax
88 deltax=2.d0*deltax
89 251 continue
90c
91 read(55,*)ne,iys,ixc
92c ne: no. bound states
93c iys: =1 for spin compensated; =2 spin polarized
94c ixc: = 1 b-h xc; =0 c-a xc
95 if(ixc.eq.1)write(66,2149)
96 if(ixc.eq.0)write(66,2148)
97 if(ixc.eq.2)write(66,2147)
982149 format(/' von barth - hedin xc')
992148 format(/' ceperley - alder xc')
1002147 format(/' perdew - wang xc')
101 dxx=r(n)-r(n-1)
102 write(66,5)jblock,nbl,c
103 write(66,5849)dx,dxx,r(n)
104 5 format(/' hermann-skillmann mesh',/,' blocks, nbl, c:',2(i5,','),
105 j f10.7)
1065849 format(' first interval, last interval, final r:',2(f10.6,','),
107 j f10.6)
108 write(66,2312) thresh,qsc,fback
1092312 format(/' energy eigenvalue threshold, screening parameter, ',
110 j 'feedback:',2(f12.6,','),f6.3)
111 write(66,9)
112 do 5273 i=1,7
1135273 nb(i)=0
114 lmax=0
1159 format(//' initial bound state configuration',/,
116 j ' nlm energy occup. val.el. d-band el.')
117 zv=0.d0
118 do 5595 ispin=1,iys
119 do 5595 ii=1,ne
120 read(55,*)nnlz,eb0,rnoc,nv,ndv
121c
122c nnlz : e.g. 100
123c eb0 : energy eigenvalue guess
124c rnoc : occupation number
125c nv : =1 when orbital is a valence orbital; =0 for core orbitals
126c ndv : =1 when orbital is a d-valence orbital; =0 for other orbitals
127c
128 nnn=nnlz/100
129 lll=(nnlz-nnn*100)/10
130 nnn=nnn-lll
131 if(nnn.gt.nb(lll+1))nb(lll+1)=nnn
132 if(lll.gt.lmax)lmax=lll
133 rnocc(ispin,lll+1,nnn)=rnoc
134 nval(ispin,lll+1,nnn)=nv
135 ndval(ispin,lll+1,nnn)=ndv
136 if(iys.eq.1)nval(2,lll+1,nnn)=nv
137 if(iys.eq.1)ndval(2,lll+1,nnn)=ndv
138 if(iys.eq.1)rnocc(2,lll+1,nnn)=rnoc
139 if(iys.eq.1)rnoc=rnoc*2
140 write(66,19)nnlz,eb0,rnoc,nv,ndv
141 zv=zv+rnoc*(nv+ndv)
1425595 ebound(ispin,lll+1,nnn)=eb0
143 write(66,5120)zv
1445120 format(/' number of valence electrons: ',f5.1)
145 19 format(i6,e12.4,f7.2,i7,i10)
146 nb1=nbl+1
147 iter=0
148 itr=itmax-iout
149c
150 16 format(7(f12.5,1x))
151 17 format(/' charge and spin density profiles '/)
152 18 format(1h0/' potentials vs. distance after ',i3,' iterations'/)
153c
154c tabulate screened green's function
155 do 10 i=1,n
156 10 gr(i)=exp(-qsc*r(i))
157c
158c integration weigths
159 do 121 i=1,nb1
160 121 wj(i)=(3.d0+(-1.d0)**i)/3.d0
161 wj(1)=1.d0/3.d0
162 wj(nb1)=1.d0/3.d0
163c
164c initial values of the potentials
165 if(inopt.eq.1) goto 302
166 if(inopt.eq.2) goto 306
167c
168 itt=0
169c thomas-fermi potential
170 do 30 i=2,n
171 x=r(i)/0.88534135d0*z**(1.d0/3.d0)
172 xx=sqrt(x)
173 vc(i)=-z/r(i)/(1.+0.02747d0*xx+1.243d0*x-0.1486d0*x*xx
174 j+0.2302d0*x*x+0.007298d0*x*x*xx+0.006944d0*x*x*x)
175 do 30 ispin=1,2
176 30 veff(ispin,i)=vc(i)
177 goto 311
178c read in an old potential for the input
179302 read(33,2645)itt
1802645 format(i3)
1811645 format(i3,' z,ion:',2f4.0,' jblock,nbl,c:',2i5,f10.7)
182 do 303 i=1,n
183 303 read(33,907) vc(i),veff(1,i),veff(2,i),du1,du2
184 goto 311
185 306 read(46,2645) itt
186 do 304 i = 1, n
187 read(46,*) du1, vc(i), vve, du2
188 veff(1,i) = vve
189 veff(2,i) = vve
190 304 continue
191 311 do 312 i=1,n
192 vcold(i)=vc(i)
193 do 312 ispin=1,2
194 312 vold(ispin,i)=veff(ispin,i)
195 5555 format(e15.8)
196 7771 format(/' initial potentials'/)
197 7773 format(5f13.5)
198 if(iout.lt.-1)go to 1437
199 write(66,7771)
200 do 7772 i=2,n,ipr
201 7772 write(66,7773) r(i),vc(i),veff(1,i),veff(2,i)
2021437 eold=0.d0
203 etot=-1.d0
204 itec=0
205c
206c iteration
207c
208 100 iter=iter+1
209c write(6,*) 'NEW ITERATION'
210c call flush(6)
211c convergency check
212 if(abs(etot-eold).lt.5.d-5)itec=itec+1
213 if(abs(etot-eold).lt.5.d-5.and.itec.eq.1)itmax=iter
214 eold=etot
215 if(iter-itmax)999,999,400
216999 itt=itt+1
217 write(66,6147)itt
218 do 117 i=1,n
219 dval(2,i)=0.d0
220 ddval(2,i)=0.d0
221 dcore(1,i)=0.d0
222 dcore(2,i)=0.d0
223 dval(1,i)=0.d0
224 117 ddval(1,i)=0.d0
225 6147 format(///' ********************* iteration:',
226 1 i4,' ***********************'/)
227 do 917 ispin=1,iys
228 do 116 i=1,n
229 vv(i)=veff(ispin,i)
230 v(i)=2*vv(i)
231 116 db(ispin,i)=0.d0
232 lm(ispin)=-1
233 do 807 i=0,4
234 ik=i
235 if(i)817,817,818
236817 do 819 jj=1,4
237819 u(jj)=r(jj)-z*r(jj)**2
238 go to 822
239818 do 821 jj=1,4
240821 u(jj)=r(jj)**(i+1)
241822 call schrhs(vv,0.d0,ik,u)
242 merkki=1
243c determine the number of bound states
244 ncross=0
245 do 826 ii=2,n
246 if(merkki)823,823,824
247823 if(u(ii))826,826,825
248824 if(u(ii))825,826,826
249825 merkki=-merkki
250 ncross=ncross+1
251826 continue
252 dlo=(u(n)-u(n-1))*u(n)
253 if(dlo.ge.0)nbound(ispin,i+1)=ncross
254 if(dlo.lt.0)nbound(ispin,i+1)=ncross+1
255 if(nbound(ispin,i+1).eq.0)go to 827
256 lm(ispin)=i
257 write(66,678)i,nbound(ispin,i+1)
258 nbound(ispin,i+1)=min0(nbound(ispin,i+1),nb(i+1))
259678 format(' l = ',i4,',',i4,' bound states ')
260807 continue
261827 if(lm(ispin).lt.0.and.ispin.eq.2)go to 674
262 if(lm(ispin).lt.0.and.ispin.eq.1)go to 917
263 lm(ispin)=min0(lm(ispin),lmax)
264 lmm=lm(ispin)
265 do 918 i=0,lmm
266 nii=min0(nbound(ispin,i+1),8)
267 ik=i
268 do 918 ii=1,nii
269 if(rnocc(ispin,i+1,ii).lt.0.1d0)go to 918
270 nn=i+ii
271 en=2.d0*ebound(ispin,i+1,ii)
272 if(en.ge.0.d0)en=en0
273 en1=en
274 dde=de(ispin,i+1,ii)
275 if(iter.le.2)dde=0.d0
276c determine the bound state energy and eigenfunction
277 call scheq(z,en,ik,nn,mest,mesh,c,thresh,iflag,npr,dde)
278c scheq operates in rydberg units
279 if(iter.ge.2)de(ispin,i+1,ii)=abs(en-en1)
280 if(iflag.eq.1) goto 400
281 163 ebound(ispin,i+1,ii)=en/2.d0
282 nlp(ispin,i+1,ii)=npr
283 do 9188 ji=1,n
284 dval(ispin,ji)=dval(ispin,ji)+rnocc(ispin,i+1,ii)*snlo(ji)**2/sf
285 j*nval(ispin,i+1,ii)
286 ddval(ispin,ji)=ddval(ispin,ji)+rnocc(ispin,i+1,ii)*snlo(ji)**2/
287 j sf*ndval(ispin,i+1,ii)
288 dcore(ispin,ji)=dcore(ispin,ji)+rnocc(ispin,i+1,ii)*snlo(ji)**2/
289 j sf*(1-ndval(ispin,i+1,ii))*(1-nval(ispin,i+1,ii))
290 9188 db(ispin,ji)=db(ispin,ji)+rnocc(ispin,i+1,ii)*snlo(ji)**2/sf
291 918 continue
292 do 919 ji=2,n
293 dcore(ispin,ji)=dcore(ispin,ji)/r(ji)**2
294 919 db(ispin,ji)=db(ispin,ji)/r(ji)**2
295 db(ispin,1)=db(ispin,2)
296 dcore(ispin,1)=dcore(ispin,2)
297 do 5739 ji=2,n
298 ddval(ispin,ji)=ddval(ispin,ji)/r(ji)**2
2995739 dval(ispin,ji)=dval(ispin,ji)/r(ji)**2
300 dval(ispin,1)=dval(ispin,2)
301 ddval(ispin,1)=ddval(ispin,2)
302 917 continue
303 if(iys.eq.2)go to 923
304 do 921 i=1,n
305 dval(2,i)=dval(1,i)
306 ddval(2,i)=ddval(1,i)
307 dcore(2,i)=dcore(1,i)
308921 db(2,i)=db(1,i)
309 lmm=lm(1)
310 lm(2)=lm(1)
311 do 922 i=0,lmm
312 nii=nbound(1,i+1)
313 nbound(2,i+1)=nii
314 do 922 ii=1,nii
315922 ebound(2,i+1,ii)=ebound(1,i+1,ii)
316923 continue
317 8 format(' ',i6,' energy: ',f12.5,' iteration loops: ',i4)
318c
319c total bound state energy
320c
321c write(6,*) 'Total energy starts'
322c call flush(6)
323 661 eb=0.d0
324 ebv=0.d0
325 write(66,7496)
3267496 format(//' bound states'/)
327 do 673 ispin=1,2
328 lmm=lm(ispin)
329 do 673 i=0,lmm
330 nii=nbound(ispin,i+1)
331 do 673 j=1,nii
332 nn=i+j
333 nnlz=100*nn+10*i
334 eb=eb+ebound(ispin,i+1,j)*rnocc(ispin,i+1,j)
335 ebv=ebv+ebound(ispin,i+1,j)*rnocc(ispin,i+1,j)*
336 j (nval(ispin,i+1,j)+ndval(ispin,i+1,j))
337 if(rnocc(ispin,i+1,j).lt.0.1d0) go to 673
338 write(66,8) nnlz,ebound(ispin,i+1,j),nlp(ispin,i+1,j)
339 673 continue
340 go to 679
341674 write(66,676)
342676 format('0no bound states')
343679 continue
344c
345c total charge and spin densities
346c computing energy integrals
347c
348506 continue
349c=========================================
350c gga
351c set the "done" controle variables to false in the beginning of
352c each iteration
353
354 if (ixc.eq.2) then
355 doned = .false.
356 donela = .false.
357 donegr = .false.
358 donez = .false.
359 donec = .false.
360 endif
361c gga
362c========================================
363 do 660 i=2,n
364 roo(i)=db(1,i)+db(2,i)
365 rr=roo(i)
366c When db = (0,0) then the spin-polarization, spl = 0, and not 0/0.
367 if (rr.gt.0.0000000001) then
368 spl(i)=(db(1,i)-db(2,i))/rr
369 else
370 spl(i)=0.0
371 endif
372 x1=r(i)**2
373 apu(i)=x1*veff(1,i)*db(1,i)*sf
374 bpu(i)=x1*veff(2,i)*db(2,i)*sf
375 if (ixc.eq.2) then
376c================================================================
377c gga
378c calculate the gga exchange-correlation energy
379
380 call ggaexc(r,db,i,1,n,doned,excgga(i))
381 cpu(i) = x1*rr*excgga(i)*sf
382c gga
383c================================================================
384 else
385 cpu(i)=x1*rr*exc(rr,spl(i),ixc)*sf
386 endif
387 dpu(i)=x1*spl(i)*rr*sf
388 660 continue
389 26 format(' induced moment: ',f10.5)
390 call simpsh(apu,v1)
391 call simpsh(bpu,v2)
392 call simpsh(cpu,eexc)
393 call simpsh(dpu,smom)
394c
395c compute coulomb energy
396c
397 cz=z
398 do 683 i=1,n
399 bpu(i)=roo(i)*r(i)**2*sf
400 dpu(i)=(dval(1,i)+dval(2,i))*r(i)**2*sf
401 apu(i)=(ddval(1,i)+ddval(2,i))*r(i)**2*sf
402 cpu(i)=roo(i)*(r(i)**2*vc(i)-z*r(i))*sf/2.d0
403683 continue
404 call simpsh(dpu,sum1)
405 call simpsh(apu,sum3)
406 call simpsh(bpu,sum2)
407 call simpsh(cpu,ec)
408 24 format(' kin: ',2(e14.6,1x),' coul: ',e14.6,' exc: ',e14.6)
409 25 format(/' total energy: ',e15.7)
410 write(66,192) sum2,sum1,sum3
411 write(66,26) smom
412 ekin(1)=-v1
413 ekin(2)=-v2
414 etot=ekin(1)+ekin(2)+eb+ec+eexc
415 write(66,7453)
4167453 format(/' energy terms')
417 write(66,622)eb
418 622 format(' energy eigenvalue sum: ',e14.6)
419 write(66,24) ekin(1),ekin(2),ec,eexc
420 write(66,25) etot
421c write(6,2573) itt,sum2,etot
422c call flush(6)
423c2573 format(' iter:',i4,' total ch:',f6.2,' total en:',f15.7)
424 write(6,2573) itt,etot
425 call flush(6)
4262573 format(' ',i4,' ',f15.5)
427
428 if(iter.ne.1 .and. iter.lt.itr) goto 167
429 if(iout.lt.0)go to 167
430 write(66,17)
431 192 format(/' integr charges: total ',f10.7,' valence: ',2f10.7)
432 do 166 i=1,n,ipr
433 r22=r(i)*r(i)
434 db1=db(1,i)
435 db2=db(2,i)
436 dr=db1+db2
437 dcc=dcore(1,i)+dcore(2,i)
438 dvv=dval(1,i)+dval(2,i)+ddval(1,i)+ddval(2,i)
439 ddb=db1-db2
440c166 write(66,1624) r(i),db1,db2,dval(i),ddval(i),dr,ddb
441 166 write(66,1624) r(i),db1,db2,dr,dcc,dvv
442c
443c
444c compute coulomb potential
445c
446 167 do 55 i=2,n
447 55 vc(i)=r(i)*vc(i)+zion
448c write(6,*) 'Coulomb potential'
449c call flush(6)
450 zi=z-zion
451 vc(1)=-zi
452 call scrhs(roo,vc,zi,qsc,n)
453 do 50 i=2,n
454 50 vc(i)=(vc(i)-zion)/r(i)
455c
456c set up the total potential
457c
458 do 60 i=2,n
459 dr=roo(i)
460 vc(i)=(1.d0-fback)*vcold(i)+fback*vc(i)
461 vcold(i)=vc(i)
462 if (ixc.eq.2) then
463c================================================================
464c gga
465c calculate the gga exchange-correlation potential
466
467 call ggauxc(r,db,spl,i,1,n,donela,donegr,donez,
468 j uxcup(i),uxcdn(i))
469 ux1(i) = uxcup(i)
470 ux2(i) = uxcdn(i)
471c gga
472c================================================================
473 else
474 ux1(i)=uxc(dr,spl(i),1,ixc)
475 ux2(i)=uxc(dr,spl(i),2,ixc)
476 endif
477 6848 veff(1,i)=vc(i)+ux1(i)
478 veff(2,i)=vc(i)+ux2(i)
479 do 60 ispin=1,2
480 veff(ispin,i)=(1.d0-fback)*vold(ispin,i)+fback*veff(ispin,i)
481 60 vold(ispin,i)=veff(ispin,i)
482c calculate the valence energy
483 do 5100 i=2,mesh
484 do 5110 j=1,mesh
485 apu(j)=0.d0
486 if(i.le.j)apu(j)=(dval(1,j)+dval(2,j)+ddval(1,j)+ddval(2,j))*
487 j (r(j)**2/r(i)-r(j))
4885110 continue
489 call simpsh(apu,vp)
4905100 vhv(i)=-vp*4.d0*pi+zv/r(i)
491 do 5130 i=1,mesh
492 x1=r(i)**2
493 rr=db(1,i)+db(2,i)
494 spt=0.d0
495 if(rr.gt.1.d-10)spt=(db(1,i)-db(2,i))/rr
496 rrv=dval(1,i)+dval(2,i)+ddval(1,i)+ddval(2,i)
497 spv=0.d0
498 if(rrv.gt.1.d-10)spv=(dval(1,i)-dval(2,i)+ddval(1,i)-ddval(2,i))
499 j /rrv
500 rrc=dcore(1,i)+dcore(2,i)
501 spc=0.d0
502 if(rrc.gt.1.d-10)spc=(dcore(1,i)-dcore(2,i))/rrc
503 apu(i)=-0.5d0*x1*sf*rrv*vhv(i)
504 if (ixc.eq.2) then
505c=============================================================
506c gga
507c calculate the gga exchange-correlation energy for core electrons
508
509 if (rrc.lt.1.d-100) then
510 excgac = 0.d0
511 else
512 call ggaexc(r,dcore,i,1,n,donec,excgac)
513 endif
514 bpu(i)=x1*rr*excgga(i)*sf
515 cpu(i)=-x1*rrc*excgac*sf
516 fpu(i)=(dcore(1,i)+dcore(2,i))*excgga(i)*x1*sf
517 dpu(i)=(-(dval(1,i)+ddval(1,i))*uxcup(i)
518 j -(dval(2,i)+ddval(2,i))*uxcdn(i))*sf*x1
519c gga
520c==================================================================
521 else
522 bpu(i)=x1*rr*exc(rr,spt,ixc)*sf
523 cpu(i)=-x1*rrc*exc(rrc,spc,ixc)*sf
524 fpu(i)=(dcore(1,i)+dcore(2,i))*exc(rr,spt,ixc)*x1*sf
525 dpu(i)=(-(dval(1,i)+ddval(1,i))*uxc(rr,spt,1,ixc)
526 j -(dval(2,i)+ddval(2,i))*uxc(rr,spt,2,ixc))*sf*x1
527 endif
528 epu(i)=apu(i)+bpu(i)+cpu(i)+dpu(i)+fpu(i)
5295130 continue
530c call simpsh(apu,ec)
531c call simpsh(bpu,eext)
532c call simpsh(fpu,eexx)
533c call simpsh(cpu,eexc)
534c call simpsh(dpu,eexv)
535c etv=ebv+ec+eext+eexc+eexv
536 call simpsh(epu,etv)
537 etv = etv + ebv
538 write(66,5140)etv
5395140 format(' valence energy:',e15.7)
540 if(iter.ne.1 .and. iter.lt.itr) go to 100
541 if(iout.lt.0)go to 100
542 write(66,18) itt
543 do 75 i=2,n,ipr
544 dr=roo(i)
545 75 write(66,1624) r(i),vc(i),ux1(i),ux2(i),veff(1,i),veff(2,i)
5461624 format(1x,f12.5,6e14.5)
547 goto 100
548 400 continue
549c
550c
551c
552 do 1140 i=2,mesh
553 do 1130 j=1,mesh
554 apu(j)=0.d0
555 if(i.le.j)apu(j)=(db(1,j)+db(2,j))*(r(j)**2/r(i)-r(j))
5561130 continue
557 call simpsh(apu,vp)
5581140 vc(i)=-vp*sf
559 write(22,1645)itt,z,zion,jblock,nbl,c
560 write(44,1645)itt,z,zion,jblock,nbl,c
561 do 900 i=1,n
562 dd=db(1,i)+db(2,i)
563 dc=dcore(1,i)+dcore(2,i)
564 dddc = dd + dc
565 dv1=dval(1,i)+dval(2,i)
566 ddv1=ddval(1,i)+ddval(2,i)
567 vve = 0.5d00*(veff(1,i) + veff(2,i))
568 write(44,*) r(i), vc(i), vve, dddc
569c The line below writes total and core densities to atomdens.dat (J.H.)
570 write(77,906) r(i), 4*pi*dd*r(i)*r(i), 4*pi*dc*r(i)*r(i)
571 write(22,907)vc(i),veff(1,i),veff(2,i),dddc,r(i)
572 900 continue
573 907 format(6e15.7)
574c900 write(22,906)vc(i),veff(1,i),veff(2,i),dd,dc
575c900 write(22,906)vc(i),veff(1,i),veff(2,i),dd,dv1,ddv1
576 906 format(6e20.12)
577 write(6,*) '================================'
578 call flush(6)
579c ieeer=ieee_flags('clear','exception','all',ieeeout)
580 close(6)
581 close(22)
582 close(33)
583 close(55)
584 close(66)
585 close(77)
586 stop
587 end
diff --git a/src/labat/laplac.f b/src/labat/laplac.f
new file mode 100644
index 0000000..9a7dfd9
--- /dev/null
+++ b/src/labat/laplac.f
@@ -0,0 +1,41 @@
1 subroutine laplac(r,gradup,graddn,i,imin,imax,done,
2 j lapl,laplup,lapldn)
3c calculates laplace(density), i.e. (del^2)(density)
4c spherical coordinates => (del^2)phi = 1/r^2*d/dr[r^2*d(phi)/dr]
5c input r : radial coordinate (array)
6c input gradup : grad(density), spin up (array)
7c input graddn : grad(density), spin down (array)
8c input i : counter, i.e. current position = r(i)
9c input imin : min value of i
10c input imax : max value of i
11c in/output done : true if r^2*grad(density) is splined
12c output lapl : laplace(density)
13c output laplup,lapldn : laplace(density), spin up and down
14 implicit logical (a-z)
15 logical done
16 double precision r,gradup,graddn,lapl,laplup,lapldn,lapl2,temp
17 double precision rj2,r2,deriv
18 integer i,imin,imax,j
19 common/ggalap/temp,lapl2
20 dimension r(561),gradup(561),graddn(561)
21 dimension lapl2(2,561),temp(2,561)
22 if (.not.done) then
23 do 10 j = imin,imax
24 rj2 = r(j)**2
25 temp(1,j) = rj2*gradup(j)
26 temp(2,j) = rj2*graddn(j)
27 10 continue
28 call spline(r,imin+1,imax,temp,lapl2)
29 done = .true.
30 endif
31 if (i.eq.imin) then
32 call laplac2(r,gradup,graddn,i+1,imin,imax,done,lapl,laplup,
33 j lapldn)
34 else
35 r2 = r(i)**2
36 laplup = (deriv(r,temp,lapl2,1,i,imin,imax))/r2
37 lapldn = (deriv(r,temp,lapl2,-1,i,imin,imax))/r2
38 lapl = laplup + lapldn
39 endif
40 return
41 end
diff --git a/src/labat/laplac2.f b/src/labat/laplac2.f
new file mode 100644
index 0000000..f2cce8b
--- /dev/null
+++ b/src/labat/laplac2.f
@@ -0,0 +1,11 @@
1 subroutine laplac2(r,gradup,graddn,i,imin,imax,done,
2 j lapl,laplup,lapldn)
3 implicit logical (a-z)
4 logical done
5 double precision r,gradup,graddn,lapl,laplup,lapldn
6 integer i,imin,imax
7 dimension r(561),gradup(561),graddn(561)
8 call laplac(r,gradup,graddn,i+1,imin,imax,done,lapl,laplup,
9 j lapldn)
10 return
11 end
diff --git a/src/labat/ldaec.f b/src/labat/ldaec.f
new file mode 100644
index 0000000..01e18ca
--- /dev/null
+++ b/src/labat/ldaec.f
@@ -0,0 +1,21 @@
1 subroutine ldaec(rs,zet,ec)
2c uniform-gas correlation of perdew and wang 1991
3c calculates the local correlation energy within the lda approx.
4c input rs : seitz radius
5c input zet : relative spin polarization
6c output ec : correlation energy per electron
7 implicit double precision (a-h,o-z)
8 data gam,fzz/0.5198421d0,1.709921d0/
9 data thrd4/1.333333333333d0/
10 f = ((1.d0+zet)**thrd4+(1.d0-zet)**thrd4-2.d0)/gam
11 call gcor(0.0310907d0,0.21370d0,7.5957d0,3.5876d0,1.6382d0,
12 1 0.49294d0,1.00d0,rs,eu,eurs)
13 call gcor(0.01554535d0,0.20548d0,14.1189d0,6.1977d0,3.3662d0,
14 1 0.62517d0,1.00d0,rs,ep,eprs)
15 call gcor(0.0168869d0,0.11125d0,10.357d0,3.6231d0,0.88026d0,
16 1 0.49671d0,1.00d0,rs,alfm,alfrsm)
17c alfm is minus the spin stiffness alfc
18 z4 = zet**4
19 ec = eu*(1.d0-f*z4)+ep*f*z4-alfm*f*(1.d0-z4)/fzz
20 return
21 end
diff --git a/src/labat/ldauc.f b/src/labat/ldauc.f
new file mode 100644
index 0000000..4285c9a
--- /dev/null
+++ b/src/labat/ldauc.f
@@ -0,0 +1,32 @@
1 subroutine ldauc(rs,zet,ec,ecrs,eczet,vcup,vcdn)
2c uniform-gas correlation of perdew and wang 1991
3c calculates the local correlation potential within the lda approx.
4c input rs : seitz radius
5c input zet : relative spin polarization
6c output ec : correlation energy
7c output ecrs : derivative of ec with respect to rs
8c output eczet : derivative of ec with respect to zet
9c output vcup, vcdn : up- and down-spin potentials
10 implicit double precision (a-h,o-z)
11 data gam,fzz/0.5198421d0,1.709921d0/
12 data thrd,thrd4/0.333333333333d0,1.333333333333d0/
13 f = ((1.d0+zet)**thrd4+(1.d0-zet)**thrd4-2.d0)/gam
14 call gcor(0.0310907d0,0.21370d0,7.5957d0,3.5876d0,1.6382d0,
15 1 0.49294d0,1.00d0,rs,eu,eurs)
16 call gcor(0.01554535d0,0.20548d0,14.1189d0,6.1977d0,3.3662d0,
17 1 0.62517d0,1.00d0,rs,ep,eprs)
18 call gcor(0.0168869d0,0.11125d0,10.357d0,3.6231d0,0.88026d0,
19 1 0.49671d0,1.00d0,rs,alfm,alfrsm)
20c alfm is minus the spin stiffness alfc
21 z4 = zet**4
22 ec = eu*(1.d0-f*z4)+ep*f*z4-alfm*f*(1.d0-z4)/fzz
23c energy done. now the potential:
24 ecrs = eurs*(1.d0-f*z4)+eprs*f*z4-alfrsm*f*(1.d0-z4)/fzz
25 fz = thrd4*((1.d0+zet)**thrd-(1.d0-zet)**thrd)/gam
26 eczet = 4.d0*(zet**3)*f*(ep-eu+alfm/fzz)+fz*(z4*ep-z4*eu
27 1 -(1.d0-z4)*alfm/fzz)
28 comm = ec -rs*ecrs/3.d0-zet*eczet
29 vcup = comm + eczet
30 vcdn = comm - eczet
31 return
32 end
diff --git a/src/labat/resten.f b/src/labat/resten.f
new file mode 100644
index 0000000..8314dad
--- /dev/null
+++ b/src/labat/resten.f
@@ -0,0 +1,634 @@
1c *********************************************************************
2 subroutine scheq(zz,en,lambda,nofl,kkk,mess,scf,thresh,iflag,npr
3 1,de)
4 implicit double precision (a-h,o-z)
5c subroutine scheq
6c compute energy eigenvalue and wave function
7c originally written by sherwood skillman
8c rca laboratories, princeton, new jersey, spring 1961
9c modified by frank herman, summer 1961
10c further modified by richard kortum and paul kelly, lockheed
11c research laboratories, palo alto, california, summer 1962
12c further modified by r.m. nieminen, otaniemi,spring 1978
13c and last but not least modified by m.p. winter 1979
14 dimension qq(561),p(5),q(5),t(5),d(5)
15 common/sc/gr(561),r(561),snlo(561),nbl
16 common/pot/v(561)
17 imp=1
18 nb1=nbl+1
19 nmb=nb1/5
20 if (de.lt.1.d-10)imp=0
21 if(imp.eq.1)de=dmax1(de,-e/500.d0)
22 eg=0.d0
23 z=zz
24 lam=lambda
25 nn=nofl
26 mesh=mess
27 c=scf
28 i0=0
29 many = 150
30 iflag=0
31 73 e=en
32 morev=0
33 lessv=0
34 emore=0.0d0
35 eless=0.0d0
36 more=0
37 less=0
38 mp=0
39 nprint=0
40 lamm=lam-1
41 lamp=lam+1
42 xlp=lamp
43 ndcr=nn-lamp
44 b=lam*lamp
45 oc=r(2)
46 h=oc
47 hsq=h*h
48 b3=(v(3)-v(2))/h-z/hsq
49 y=h+h
50 flps=4*lam+6
51 slpt=6*lam+12
52 elpt=8*lam+20
53 a1=-z/xlp
54 ysq=y*y
55 b1=-z-z
56 ab1=a1*b1
57 ab3=a1*b3
58c raise h and y to lam+1
59 htl=h
60 ytl=y
61 if(lam)77,1102,1100
62 1100 do 1101 i=1,lam
63 htl=htl*h
64 1101 ytl=ytl*y
65 1102 h1=hsq
66 bohs=b/hsq
67 boh=b1/h
68 bth=b3*h
69 bq3=bohs+boh+bth
70 bq4=bohs/4.d0+boh/2.d0+bth+bth
71 epl=8+lam
72 fpl=5+lam
73 xifc=c*.21701389d-4
74c start outward integration
75 10 nprint=nprint+1
76 eps =e-eg
77 eg =e
78 if(many-nprint) 900,75,75
79900 if(mp.eq.2)go to 300
80 write (6,901)nn,lam ,z
81 call flush(6)
82 901 format (21h no convergence on,i4,i1,f4.0)
83 iflag=1
84 en=0.d0
85 npr=nprint
86 return
87 77 nstop=7
88 777 write(66,770) nstop
89 770 format(' error in scheq',i6)
90 en=0.d0
91 iflag=1
92 npr=nprint
93 return
94 75 do 11 i=1,mesh
95 11 snlo(i)=0.0d0
96 if(nprint-1) 77,500,529
97 500 continue
98 do 502 i= 4,mesh
99 qq(i) = v(i)+b/(r(i)*r(i))-e
100 502 continue
101 516 m= mesh
102 do 520 i=4,mesh
103 if(qq(m)) 519,520,520
104 519 ik=m+1
105 go to 525
106 520 m=m-1
107 write(66,562)lam,qq(m+1),e
108562 format(/' l: ',i5,' q: ',g15.6,' e: ',g15.6/)
109 521 nstop =521
110c q is everywhere positive
111 go to 777
112 525 if(mesh-ik) 526,526,535
113 526 eps = qq(mesh-nbl)
114 e = e+eps
115 529 continue
116 do 530 i=4,mesh
117 530 qq(i) = qq(i)-eps
118 go to 516
119 535 continue
120 14 ncross=0
121 sig=1.0d0
122 h=oc
123 y=h+h
124c b= lam*(lam+1)
125c b1= -2.d0*z
126 b2=3.0d0*z/h-e+2.0d0*v(2)-v(3)
127c b3=(v(3)-v(2))/h -z/hsq
128c a1= -z/(lam+1)
129 a2=(ab1+b2)/flps
130c a2=(a1*b1+b2)/(4*lam+6)
131 a3=(a2*b1+a1*b2+b3)/slpt
132c a3=(a2*b1+a1*b2+b3)/(6*lam+12)
133 a4=(a3*b1+a2*b2+ab3)/elpt
134c a4=(a3*b1+a2*b2+a1*b3)/(8*lam+20)
135 p(3)=(1.0d0+h*(a1+h*(a2+h*(a3+h*a4))))*htl
136c p(3)=(1.0d0+a1*h+a2*h**2+a3*h**3+a4*h**4)*h**(xl+1.0d0)
137 p(4)=(1.0d0+y*(a1+y*(a2+y*(a3+y*a4))))*ytl
138c p(4)=(1.0d0+a1*y+a2*y**2+a3*y**3+a4*y**4)*y**(xl+1.0d0)
139 q(3)=bq3+b2
140c q(3)=(b+b1*h+b2*h**2+b3*h**3)/h**2
141 q(4)=bq4+b2
142c q(4)=(b+b1*y+b2*y**2+b3*y**3)/y**2
143 snlo(2)=p(3)
144 snlo(3)=p(4)
145 i=3
146 dx=oc
147 h1=h**2
148 h2=h1/12.0d0
149 t(3)=p(3)*(1.0d0-h2*q(3))
150 t(4)=p(4)*(1.0d0-h2*q(4))
151 d(4)=t(4)-t(3)
152 ncount=3
153 nint=2
154 15 i=i+1
155c if end of mesh is reached, modify trial eigenvalue
156 if(i-mesh) 16,3,3
157 3 if(ndcr-ncross) 32,33,33
158c return to begininning of outward integration if necessary
159 16 q(5) =qq(i)
160 if(ik-i) 29,29,21
161 21 d(5)=d(4)+h1*q(4)*p(4)
162 t(5)=d(5)+t(4)
163 if(1.0d0-abs (h2*q(5))) 3,3,501
164 501 p(5)=t(5)/(1.0d0-h2*q(5))
165 snlo(i) = p(5)
166 if(sig) 211,77,212
167 211 if(p(5)) 23,23,22
168 212 if(p(5)) 22,23,23
169 22 ncross=ncross+1
170c count changes in sign
171 sig=-sig
172 23 ncount=ncount+1
173 if(7-ncount)77,24,25
174 24 ncount=2
175 25 nint=nint+1
176 if(nbl-nint)77,26,27
177 26 dx=dx+dx
178 h=dx
179 h1=h**2
180 h2=h1/12.0d0
181 nint=0
182 t(5)=p(5)*(1.0d0-h2*q(5))
183 t(3)=p(3)*(1.0d0-h2*q(3))
184 d(5)=t(5)-t(3)
185 27 do 28 k=1,4
186 p(k)=p(k+1)
187 t(k)=t(k+1)
188 d(k)=d(k+1)
189 28 q(k)=q(k+1)
190 go to 15
191 29 if(ncount-2)77,30,21
192 30 if(nint-4)21,21,31
193c matching radius has been reached going out
194c if ndcr not equal to ncross,modify trial eigenvalue
195 31 eigen=e
196 if(ndcr-ncross) 32,35,33
197 32 more=1
198 mp=0
199c too many crossings, increase absf(e)
200 morev=morev+1
201 if(morev-1) 50,53,52
202 50 nstop=50
203 go to 777
204 52 if(e -emore) 53,54,54
205 53 emore=e
206 54 if (less) 55,56,64
207 55 nstop=55
208 go to 777
209 56 e=1.25d0*eg
210 go to 10
211 33 less=1
212 mp=0
213c too few crossings, decrease abs (e)
214 lessv=lessv+1
215 if(lessv-1) 57,60,59
216 57 nstop=57
217 go to 777
218 59 if(eless- e) 60,61,61
219 60 eless=e
220 61 if(more) 62,63,64
221 62 nstop=62
222 go to 777
223 63 e=0.75d0*eg
224 go to 10
225 64 e=0.5d0*(emore+eless)
226 go to 10
227 35 if(abs (snlo(i-1))-abs (snlo(i-2))) 351,354,354
228c check to see that wave is in the damped region (absolute value
229c decreasing and signs alike)
230 351 if (p(5)) 352,21 ,353
231 352 if(snlo(i-2)) 401,21,21
232 353 if(snlo(i-2)) 21,21,401
233 354 if(1.0d+25 -abs (p(5)))33,33,21
234c large absolute value of p in what should be the damped region
235c indicates too few peaks, decrease absf(e)
236c now ndcr = ncross and matching radius lies in damped region
237 401 imatch=i-2
238 xmatch=r(i-2)
239 ppout=(t(4)-t(2)-0.5d0*(p(4)-p(2)))/h
240 s2=ppout/p(3)
241c integration is by 8 applications of newton-cotes closed
242c quadrature for five intervals on each block
243c xifc =(5*h(block 1)/288)/2 ,h(1) =0.0025*scale factor
244 sum1=0.0d0
245 xif=xifc
246 i=1
247 value=0.0d0
248 36 mm=nmb
249 sum2=0.0d0
250 xif=xif+xif
251 37 y=value
252 value=snlo(i+5)**2
253 sum2=sum2+19.d0*(value+y)+75.d0*(snlo(i+4)**2+snlo(i+1)**2)
254 1 +50.0d0*(snlo(i+2)**2+snlo(i+3)**2)
255 i=i+5
256 if (imatch-i) 77,39,371
257 371 mm=mm-1
258 if(mm)77,38,37
259 38 sum1=sum2*xif+sum1
260 go to 36
261 39 sum1= sum1+sum2*xif
262 40 s1=sum1/p(3)**2
263 pmatch=p(3)
264 if(nn-1)77,41,42
265 41 xinw=epl* xmatch
266c for n =1, start inward integration at(8+lam)*xmatch or x max
267 go to 421
268 42 xinw=fpl*xmatch
269c for n not=1, start at (5+lam)*xmatch or x max (end of mesh)
270 421 do 44 i= nb1,mesh,nbl
271 if(xinw-r(i)) 43,43,44
272 43 kkk =i
273 go to 45
274 44 continue
275 kkk =mesh
276 45 i =kkk
277 dx =r(i-1)-r(i)
278 h =dx
279 xif=0.17361111d-1*dx
280 hsq=h*h
281 hsq12=hsq/12.0d0
282 q(3)= qq(i)
283 p(3)= exp (-r(i)*sqrt (q(3)))
284 402 sum3=p(3)/q(3)
285 i=i-1
286 q(4) =qq(i)
287 404 p(4)=exp (-r(i)*sqrt (q(4)))
288 if (abs (p(4))-1.0d-35) 4041,4041,405
289 4041 kkk=kkk -nbl
290 if(kkk -imatch) 4042,4042,45
291 4042 write (5,4043)z ,nn,lam,kkk
292 4043 format (6hoat z=,f6.0,6h nl =,i3,i1,7h kkk =,i5,22h is less tha
293 1n imatch =,i5,44h inward integration will be tried at kkk+nbl)
294 kkk =kkk +nbl
295 p(4) = 1.5d-35
296 p(3) = 1.0d-35
297 405 if(pmatch)102,77,103
298 102 p(3)=-p(3)
299 p(4)=-p(4)
300 103 snlo(i+1)=p(3)
301 snlo(i)=p(4)
302 t(3)=p(3)*(1.0d0-hsq12 *q(3))
303 t(4)=p(4)*(1.0d0-hsq12*q(4))
304 d(4)=t(4)-t(3)
305 104 do 106 m=2,nbl
306 i=i-1
307 q(5) =qq(i)
308 d(5)=hsq*q(4)*p(4)+d(4)
309 t(5)=d(5)+t(4)
310 p(5)=t(5)/(1.0d0-hsq12*q(5))
311 if(i-imatch+1)77,200,105
312 105 snlo(i)=p(5)
313 do 106 k=1,4
314 p(k)=p(k+1)
315 t(k)=t(k+1)
316 d(k)=d(k+1)
317 106 q(k)=q(k+1)
318 q(5) =qq(i-2)
319 d(5)=hsq*q(4)*p(4)+d(4)
320 t(5)=d(5)+t(4)
321 p(5)=t(5)/(1.0d0-hsq12*q(5))
322 p(5)=1.09375d0*p(4)+0.2734375d0*p(5)-0.546875d0*p(3)+0.21875d0*
323 1 p(2)-0.0390625d0*p(1)
324 i=i-1
325 dx=dx/2.0d0
326 q(5) =qq(i)
327 h=dx
328 hsq=h*h
329 hsq12=hsq/12.0d0
330 t(5)=p(5)*(1.0d0-hsq12*q(5))
331 t(4)=p(4)*(1.0d0-hsq12*q(4))
332 d(5)=t(5)-t(4)
333 snlo(i)=p(5)
334 do 107 l=1,4
335 p(l)=p(l+1)
336 t(l)=t(l+1)
337 d(l)=d(l+1)
338 107 q(l)=q(l+1)
339 go to 104
340c matching radius has been reached coming in
341 200 k=kkk
342 value=snlo(k)**2
343 go to 202
344 2001 continue
345 201 sum3=sum3+xif*sum4
346 xif =xif*0.5d0
347 202 mm=nmb
348 sum4 =0.0d0
349 203 y=value
350 value=snlo(k-5)**2
351 sum4=sum4+19.d0*(value+y)+75.d0*(snlo(k-1)**2+snlo(k-4)**2)
352 1+50.0d0*(snlo(k-2)**2+snlo(k-3)**2)
353 k=k-5
354 if(k-imatch) 77,2031,2030
355 2030 mm=mm-1
356 if(mm) 77,2001,203
357 2031 sum3=sum3+xif*sum4
358 204 s3=sum3/p(4)**2
359 ppin=(t(5)-t(3)-0.5d0*(p(5)-p(3)))/h
360 s4=ppin/p(4)
361 fe=s4-s2
362 if(abs(fe).lt.1.d-08)go to 300
363c write(66,4711)mp,nprint,e,fe
364 ml=more*less
3654711 format(' mp',i2,' iter: ',i4,' e: ',e12.6,' fe: ',e12.6)
366 if(mp.eq.2)go to 9120
367 if(mp.eq.1)go to 9100
368 mp=1
369 if(imp.eq.0)de=-e/10.d0
370 de=dmin1(de,-e/10.d0)
371 if(i0.gt.0)de=de/5**i0
372 i0=i0+1
373 if(ml.gt.0)de=abs(emore-eless)/10.d0
374 if(e.gt.-1.d-35)de=1.d-7
375 eold=e
376 feold=fe
377 if(fe.gt.0)e=e-de
378 if(fe.lt.0)e=e+de
379 go to 10
3809100 if(fe*feold.lt.0)go to 9110
381 if(fe.gt.0.d0.and.imp.eq.0) de=-e/10.d0
382 if(i0.gt.1.and.ml.gt.0)de=abs(emore-eless)/10.d0
383 eold=e
384 feold=fe
3859101 if(fe.lt.0d0)e=e+de
386 if(fe.gt.0d0)e=e-de
387 go to 10
3889110 continue
3899111 mp=2
390 fe1=feold
391 fe2=fe
392 e1=eold
393 e2=e
394 eold=e
395 go to 9130
3969120 if(fe1*fe.lt.0d0)e2=e
397 if(fe1*fe.lt.0d0)fe2=fe
398 if(fe2*fe.lt.0d0)e1=e
399 if(fe2*fe.lt.0d0)fe1=fe
400 eold=e
4016174 format(' e1: ',e12.6,' fe1: ',e12.6,' e2: ',e12.6,
402 j' fe2: ',e12.6)
4039130 e=(e1*fe2-e2*fe1)/(fe2-fe1)
404 if(abs((e2-e1)/e).lt.thresh)go to 300
405 if(abs((e-eold)/e).lt.1d-06)go to 300
406 go to 10
407 300 pop=pmatch/p(4)
408 do 302 j=imatch,kkk
409 302 snlo(j)=snlo(j)*pop
410 sum1=0.0d0
411 j=1
412 xif=xifc
413 value=0.0d0
414 303 mm=nmb
415 xif=xif+xif
416 sum2=0.0d0
417 304 y=value
418 value=snlo(j+5)**2
419 sum2=sum2+19.d0*(value+y)+75.d0*(snlo(j+4)**2+snlo(j+1)**2)
420 1+50.d0*(snlo(j+2)**2+snlo(j+3)**2)
421 j=j+5
422 mm=mm-1
423 if(mm)77,305,304
424 305 sum1=sum1+xif*sum2
425 if(kkk-j)77,307,303
426 307 c1=sqrt (sum1)
427 if(snlo(3))308,77,310
428 308 c1=-c1
429c
430c include tail
431c
432 310 tail=snlo(mesh)**2/(2.d0*sqrt(abs(e)))
433 c1=c1+tail
434 do 311 i=1,kkk
435 311 snlo(i)=snlo(i)/c1
436 en=e
437 if(abs(en).lt.1.d-6) iflag=1
438 npr=nprint
439 return
440 end
441c **********************************************************************
442 subroutine simpsh(ff,s)
443 implicit double precision (a-h,o-z)
444c integrates the matrix ff on the herman-skillman mesh
445 common/mess/wj(301),dx,nblock,jblock
446 common/sc/gr(561),r(561),snlo(561),nbl
447 dimension ff(561)
448 nb1=nbl+1
449 s=0.d0
450 deltax=dx
451 do 10 j=1,jblock
452 do 11 jk=1,nb1
453 i=(j-1)*nbl+jk
454 11 s=s+ff(i)*wj(jk)*deltax
455 10 deltax=2.d0*deltax
456 return
457 end
458c **********************************************************************
459 subroutine scrhs(roo,u,z,q,n)
460 implicit double precision (a-h,o-z)
461c evaluates the screened poisson integral
462c in the herman-skillman mesh
463 dimension roo(561),u(561),ss(561),apu(561)
464 common/sc/gr(561),r(561),snlo(561),nbl
465 pi=4.d0*atan(1.d0)
466 c=4.d0*pi
467 do 11 i=1,n
468 11 ss(i)=-c*roo(i)*r(i)-q**2*u(i)
469 do 20 i=1,n
470 do 30 j=1,n
471 aa=gr(i)/gr(j)
472 if(j.gt.i) aa=1.d0/aa
473 ab=gr(i)*gr(j)
474 30 apu(j)=(aa-ab)*ss(j)
475 call simpsh(apu,s)
476 20 u(i)=-s/(2.d0*q)-z*gr(i)
477 return
478 end
479c **********************************************************************
480 function exc(r,s,ixc)
481 implicit double precision (a-h,o-z)
482c ceperley alder perdew zunger
483c or von barth hedin
484 data gp,bp1,bp2,gf,bf1,bf2/-.1423d0,1.0529d0,.3334d0,-.0843d0,
485 j1.3981d0,.2611d0/
486 data ap,bp,cp,dp,af,bf,cf,df/.0311d0,-.048d0,.002d0,-.0116d0,
487 j.01555d0,-.0269d0,.0007d0,-.0048d0/
488 if(r.lt.1.d-25)go to 100
489 pi=4.d0*atan(1.d0)
490 if(s.gt.0.99999999d0)s=0.99999999d0
491 if(s.lt.-0.99999999d0)s=-0.99999999d0
492 sinv=(4.d0*pi*r/3.d0)**(1.d0/3.d0)
493 rs=1.d0/sinv
494 if(ixc.eq.1)go to 200
495 if(rs.lt.1.d0)go to 10
496 srs=sqrt(rs)
497 excp=gp/(1.d0+bp1*srs+bp2*rs)
498 excf=gf/(1.d0+bf1*srs+bf2*rs)
499 go to 20
50010 aa=log(rs)
501 excp=ap*aa+bp+cp*rs*aa+dp*rs
502 excf=af*aa+bf+cf*rs*aa+df*rs
50320 f=((1.d0+s)**(4.d0/3.d0)+(1.d0-s)**(4.d0/3.d0)-2.d0)/
504 1 (2.d0**(4.d0/3.d0)-2.d0)
505 excf=excf-.5772521d0/rs
506 excp=excp-.4581653d0/rs
507 exc=excp+f*(excf-excp)
508 return
509100 exc=0.d0
510 return
511200 x=s/2.d0+0.5d0
512 d43=4.d0/3.d0
513 rsf=rs/75.d0
514 rsf2=rsf*rsf
515 rsf3=rsf2*rsf
516 rsp=rs/30.d0
517 rsp2=rsp*rsp
518 rsp3=rsp2*rsp
519 fcf=(1.d0+rsf3)*log(1.d0+1.d0/rsf)+0.5d0*rsf-rsf2-1.d0/3.d0
520 fcp=(1.d0+rsp3)*log(1.d0+1.d0/rsp)+0.5d0*rsp-rsp2-1.d0/3.d0
521 epscp=-.0504d0*fcp
522 epscf=-.0254d0*fcf
523 epsxp=-.91633059d0/rs
524 cny=5.1297628d0*(epscf-epscp)
525 aa=.5d0**(1.d0/3.d0)
526 if(x.lt..000001d0) x=.000001d0
527 if(x.gt..999999d0) x=.999999d0
528 fx=(x**d43+(1.d0-x)**d43-aa)/(1.d0-aa)
529 exc=epsxp+epscp+fx*(cny+4.d0/3.d0*epsxp)/5.1297628d0
530 exc=exc/2.d0
531 return
532 end
533c **********************************************************************
534 function uxc(r,s,ispin,ixc)
535 implicit double precision (a-h,o-z)
536c ceperley alder perdew zunger
537 data gp,bp1,bp2,gf,bf1,bf2/-.1423d0,1.0529d0,.3334d0,-.0843d0,
538 j1.3981d0,.2611d0/
539 data ap,bp,cp,dp,af,bf,cf,df/.0311d0,-.048d0,.002d0,-.0116d0,
540 j.01555d0,-.0269d0,.0007d0,-.0048d0/
541 if(r.lt.1.d-35)go to 100
542 pi=4.d0*atan(1.d0)
543 sinv=(4.d0*pi*r/3.d0)**(1.d0/3.d0)
544 rs=1.d0/sinv
545 if(ixc.eq.1)go to 200
546 if(rs.lt.1.d0)go to 10
547 srs=sqrt(rs)
548 excp=gp/(1.d0+bp1*srs+bp2*rs)
549 excf=gf/(1.d0+bf1*srs+bf2*rs)
550 uxcp=excp*(1.d0+7.d0/6.d0*bp1*srs+4.d0/3.d0*bp2*rs)
551 j/(1.d0+bp1*srs+bp2*rs)
552 uxcf=excf*(1.d0+7.d0/6.d0*bf1*srs+4.d0/3.d0*bf2*rs)
553 j/(1.d0+bf1*srs+bf2*rs)
554 go to 20
55510 aa=log(rs)
556 excp=ap*aa+bp+cp*rs*aa+dp*rs
557 excf=af*aa+bf+cf*rs*aa+df*rs
558 uxcp=ap*aa+(bp-ap/3.d0)+2.d0/3.d0*cp*rs*aa+(2.d0*dp-cp)*rs/3.d0
559 uxcf=af*aa+(bf-af/3.d0)+2.d0/3.d0*cf*rs*aa+(2.d0*df-cf)*rs/3.d0
56020 f=((1.d0+s)**(4.d0/3.d0)+(1.d0-s)**(4.d0/3.d0)-2.d0)/
561 j (2.d0**(4.d0/3.d0)-2.d0)
562 ddf=4.d0/3.d0*((1.d0+s)**(1.d0/3.d0)-(1.d0-s)**(1.d0/3.d0))
563 j /(2.d0**(4.d0/3.d0)-2.d0)
564 uxc=uxcp+f*(uxcf-uxcp)+(excf-excp)*(3.d0-2.d0*ispin-s)*ddf
565 j -.6108871d0/rs*(1.d0+(3.d0-2.d0*ispin)*s)**(1.d0/3.d0)
566 return
567100 uxc=0.d0
568 return
569200 x=s/2.d0+0.5d0
570 d43=4.d0/3.d0
571 xx=0.5d0-s/2.d0
572 rsf=rs/75.d0
573 rsf2=rsf*rsf
574 rsf3=rsf2*rsf
575 rsp=rs/30.d0
576 rsp2=rsp*rsp
577 rsp3=rsp2*rsp
578 fcf=(1.d0+rsf3)*log(1.d0+1.d0/rsf)+0.5d0*rsf-rsf2-1.d0/3.d0
579 fcp=(1.d0+rsp3)*log(1.d0+1.d0/rsp)+0.5d0*rsp-rsp2-1.d0/3.d0
580 epscp=-.0504d0*fcp
581 epscf=-.0254d0*fcf
582 epsxp=-.91633059d0/rs
583 cny=5.1297628d0*(epscf-epscp)
584 aa=.5d0**(1.d0/3.d0)
585 if(x.lt..000001d0) x=.000001d0
586 if(xx.lt..000001d0) xx=.000001d0
587 if(x.gt..999999d0) x=.999999d0
588 if(xx.gt..999999d0) xx=.999999d0
589 ars=-1.22177412d0/rs+cny
590 brs=-0.0504d0*log(1.d0+30.d0/rs)-cny
591 trx1=(2.d0*x)**(1.d0/3.d0)
592 trx2=(2.d0*xx)**(1.d0/3.d0)
593 if(ispin.eq.1)vxc=ars*trx1+brs
594 if(ispin.eq.2)vxc=ars*trx2+brs
595 uxc=vxc/2.d0
596 return
597 end
598c ************************************************************
599 subroutine schrhs(v,k,l,ukl)
600 implicit double precision (a-h,o-z)
601c integrates the radial schrodinger equation
602c on the herman-skillman mesh
603 double precision k
604 dimension v(561),ukl(561),y(561)
605 common/mess/wj(301),dx,nblock,jblock
606 common/sc/gr(561),r(561),snlo(561),nbl
607 sd(i)=(2.d0*v(i)-k**2+l*(l+1)/r(i)**2)*ukl(i)
608 sdd(i)=(2.d0*v(i)-k**2+l*(l+1)/r(i)**2)*y(i)
609c initial values have been stored at ukl(1)...ukl(4)
610 nb1=nbl+1
611 hh=dx
612 do 10 i=5,nb1
613 ukl(i)=ukl(i-1)+ukl(i-3)-ukl(i-4)
614 1+hh**2/4.d0*(5.d0*sd(i-1)+2.d0*sd(i-2)+5.d0*sd(i-3))
615 10 ukl(i)=2.d0*ukl(i-1)-ukl(i-2)+
616 1hh**2/12.d0*(sd(i)+10.d0*sd(i-1)+sd(i-2))
617c set initial values for the next block
618 do 20 j=2,jblock
619 hh=2.d0*hh
620 jj=(j-1)*nbl
621 y(jj+1)=ukl(jj+1)
622 y(jj)=ukl(jj-1)
623 y(jj-1)=ukl(jj-3)
624 y(jj-2)=ukl(jj-5)
625 do 30 jk=2,nb1
626 i=jj+jk
627 y(i)=y(i-1)+y(i-3)-y(i-4)+
628 1hh**2/4.d0*(5.d0*sdd(i-1)+2.d0*sdd(i-2)+5.d0*sdd(i-3))
629 y(i)=2.d0*y(i-1)-y(i-2)+
630 1hh**2/12.d0*(sdd(i)+10.d0*sdd(i-1)+sdd(i-2))
631 30 ukl(i)=y(i)
632 20 continue
633 return
634 end
diff --git a/src/labat/spline.f b/src/labat/spline.f
new file mode 100644
index 0000000..aa523be
--- /dev/null
+++ b/src/labat/spline.f
@@ -0,0 +1,34 @@
1 subroutine spline(r,start,n,db,db2)
2c spline calculates the cubic spline interpolation of the density
3c together with subroutine splint.
4c the main ideas are "stolen" from "numerical recipes", cambridge
5c university press (1992).
6c input r : position coordinate (array)
7c input start : index, r(start) = starting point of the spline
8c input n : index, r(n) = r_max
9c input db : spin up and down density. (array)
10c output db2 : second derivative of db (array)
11 implicit logical (a-z)
12 double precision r,db,db2,u,sig,p,qn,un
13 integer spin,start,n,i
14 dimension r(561),db(2,561),db2(2,561),u(561)
15 do 100 spin = 1,2
16 db2(spin,start) = 0.d0
17 u(start) = 0.d0
18 do 10 i = start+1,n-1
19 sig = (r(i)-r(i-1))/(r(i+1)-r(i-1))
20 p = sig*db2(spin,i-1)+2.d0
21 db2(spin,i) = (sig-1.d0)/p
22 u(i) = (6.d0*((db(spin,i+1)-db(spin,i))/(r(i+1)-r(i))-
23 j (db(spin,i)-db(spin,i-1))/(r(i)-r(i-1)))/
24 j (r(i+1)-r(i-1))-sig*u(i-1))/p
25 10 continue
26 qn = 0.d0
27 un = 0.d0
28 db2(spin,n) = (un-qn*u(n-1))/(qn*db2(spin,n-1)+1.d0)
29 do 20 i = n-1,start,-1
30 db2(spin,i) = db2(spin,i)*db2(spin,i+1)+u(i)
31 20 continue
32 100 continue
33 return
34 end
diff --git a/src/labat/splint.f b/src/labat/splint.f
new file mode 100644
index 0000000..a25a942
--- /dev/null
+++ b/src/labat/splint.f
@@ -0,0 +1,37 @@
1 subroutine splint(r,db,db2,spin,start,n,ri,dbi)
2c splint calculates the cubic spline interpolation of the density
3c together with subroutine spline.
4c the main ideas are "stolen" from "numerical recipes", cambridge
5c university press (1992).
6c input r : position coordinate (array)
7c input db : spin up and down density. (array)
8c input db2 : second derivative of db (array)
9c input spin : 1 if spin up, -1 if spin down
10c input start : starting point of spline = r(start)
11c input n : index, r(n) = r_max
12c input ri : position of interpolation
13c output dbi : interpolated value of db
14 implicit logical (a-z)
15 integer spin,spinn,n,klo,khi,k,start
16 double precision r,db,db2,ri,dbi,h,a,b
17 dimension r(561),db(2,561),db2(2,561)
18 spinn = spin
19 if (spinn.eq.-1) spinn = 2
20 klo = start
21 khi = n
22 10 if (khi-klo.gt.1) then
23 k = (khi+klo)/2
24 if (r(k).gt.ri) then
25 khi = k
26 else
27 klo = k
28 endif
29 goto 10
30 endif
31 h = r(khi)-r(klo)
32 a = (r(khi)-ri)/h
33 b = (ri-r(klo))/h
34 dbi = a*db(spinn,klo)+b*db(spinn,khi)+((a**3-a)*
35 j db2(spinn,klo)+(b**3-b)*db2(spinn,khi))*(h**2)/6.d0
36 return
37 end
diff --git a/src/lang/basic.cc b/src/lang/basic.cc
new file mode 100644
index 0000000..54d16a9
--- /dev/null
+++ b/src/lang/basic.cc
@@ -0,0 +1,315 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22///////////////////////////////////////////////////
23
24TOK_IMPL(asis) { out<<env.arg(0)->expr; }
25TOK_IMPL(mute) {}
26TOK_IMPL(comment) {}
27
28///////////////////////////////////////////////////
29
30TOK_IMPL(cond) {
31 Cond(*env.toks,env[0],env[1],tok_t::PUBLIC);
32}
33TOK_IMPL(global) {
34 Global(*env.toks,env[0],env[1],tok_t::PUBLIC);
35}
36TOK_IMPL(const) {
37 Const(*env.toks,env[0],env[1],tok_t::PUBLIC);
38}
39TOK_IMPL(reconst) {
40 Const(*env.toks,env[0],env[1],tok_t::PUBLIC,1);
41}
42
43///////////////////////////////////////////////////
44
45TOK_IMPL(type) {
46 tok_t* p=env.toks->get(env[0]);
47 if(env.is_clear(p)) out<<p->mod;
48}
49TOK_IMPL(desc) {
50 tok_t* p=env.toks->get(env[0]);
51 if(env.is_clear(p)) out<<Desc(*p);
52}
53TOK_IMPL(expr) {
54 tok_t* p=env.toks->get(env[0]);
55 if(env.is_clear(p)&&p->is_func()) ((func_t*)p)->x.trav(out,12);
56}
57TOK_IMPL(clear) {
58 ClearToken(*env.toks,env[0]);
59}
60
61//////////////////////////////////////////////////////
62
63TOK_IMPL(exist) { out<<env.glob_find(env[0]); }
64TOK_IMPL(nexist) { out<<!env.glob_find(env[0]); }
65TOK_IMPL(empty) { out<<env.glob(env[0]).empty(); }
66TOK_IMPL(nempty) { out<<env.glob(env[0]).nempty(); }
67
68///////////////////////////////////////////////////
69
70TOK_IMPL(export) {
71 rpile list; env.gloc_list(list,env[1]);
72 int n=*env[1]=='@'?env[1].size()-1:env[1].size();
73 for(int i=0;i<list.size();i++)
74 Global(*env.toks,env[0]+list[i].right(n),env.gloc(list[i]),tok_t::PUBLIC);
75}
76
77TOK_IMPL(import) {
78 if(*env[0]=='@') env.glob_adb(env[0].popf(),env[1]);
79 else {
80 rpile list; env.glob_list(list,env[1]);
81 for(int i=0;i<list.size();i++)
82 env.aloc(env[0]+list[i].right(env[1].size()),env.glob(list[i]));
83 }
84}
85
86TOK_IMPL(list) {
87 mstring fx; env.parg(fx,-1);
88 rpile list; env.gloc_list(list,fx);
89 int n=*fx=='@'?fx.size()-1:fx.size();
90 for(int i=0;i<list.size();i++) out<<list[i].right(n)<<"\n";
91}
92
93TOK_IMPL(globlist) {
94 mstring fx; env.parg(fx,-1);
95 rpile list; env.glob_list(list,fx);
96 int n=*fx=='@'?fx.size()-1:fx.size();
97 for(int i=0;i<list.size();i++) out<<list[i].right(n)<<"\n";
98}
99
100TOK_IMPL(lrec) {
101 sref name=env[0],first,rest=env[1];
102 mstring init; env.parg(init,-1);
103 while(Split(first,rest)) env.aloc(name+first,init);
104}
105
106///////////////////////////////////////////////////
107
108TOK_IMPL(arg) { if(env.up) env.up->parg(out,atoi(env[0])-1); }
109TOK_IMPL(args) { if(env.up) out<<env.up->args; else out<<0; }
110
111///////////////////////////////////////////////////
112
113TOK_IMPL(random) {
114 out<<Random(atoi(env[0]));
115}
116
117//////////////////////////////////////////////////////
118
119void envAddBasic(tokmap& T)
120{
121 TOK_ADD(asis,"r",tok_t::PUBLIC,
122 "%Display body as is\n"
123 "%Syntax: \\asis{body}\n"
124 );
125 TOK_ADD(mute,"x",tok_t::PUBLIC,
126 "%Evaluate but don't display\n"
127 "%Syntax: \\mute{body}\n"
128 );
129 T.add(new binary_t(sref("*"),
130 sref("%Commentary - don't show or evaluate body\n"
131 "%Syntax: \\*{body}\n"),
132 tok_t::PUBLIC,sref("r"),impl_comment),0,1);
133
134 //////////////////////////////////////////////////////
135
136 TOK_ADD(global,"xx",tok_t::PUBLIC,
137 "%Set global variable\n"
138 "%Syntax: \\global{varname}{expr}\n"
139 );
140 TOK_ADD(cond,"xx",tok_t::PUBLIC,
141 "%Set global variable if not already defined\n"
142 "%Syntax: \\cond{varname}{expr}\n"
143 );
144 TOK_ADD(const,"xx",tok_t::PUBLIC,
145 "%Set global constant\n"
146 "%Syntax: \\cond{varname}{expr}\n"
147 "%\n"
148 "%Generates an error if already defined\n"
149 );
150 TOK_ADD(reconst,"xx",tok_t::PRIVATE,
151 "%Redefine global constant\n"
152 "%Syntax: \\cond{varname}{expr}\n"
153 "%\n"
154 "%Takes precedence over any existing constant\n"
155 );
156
157 //////////////////////////////////////////////////////
158
159 TOK_ADD(type,"x",tok_t::PRIVATE,
160 "%Show variable type\n"
161 "%Syntax: \\type{varname}\n"
162 "%\n"
163 "%The type is an integer bit-field consisting of:\n"
164 "%\n"
165 "%1 CONSTANT\n"
166 "%2 RESTRICT\n"
167 "%4 NORMAL\n"
168 "%8 SYSONLY\n"
169 "%16 INIT\n"
170 "%32 RUNNABLE\n"
171 "%64 FUNCTION\n"
172 "%128 BINARY\n"
173 "%\n"
174 "%The access modes consists of\n"
175 "%\n"
176 "%INIT\n"
177 "%SYSONLY\n"
178 "%PRIVATE = NORMAL|SYSONLY\n"
179 "%PUBLIC = PRIVATE|RESTRICT\n"
180 "%\n"
181 "%Those values are matched against the running modes\n"
182 "%to determine access. See run.\n"
183 );
184 TOK_ADD(desc,"x",tok_t::PRIVATE,
185 "%Show variable description\n"
186 "%Syntax: \\desc{varname}\n"
187 "%\n"
188 "%Collects all lines starting with %.\n"
189 );
190 TOK_ADD(expr,"x",tok_t::PRIVATE,
191 "%Show the expression tree of function\n"
192 "%Syntax: \\expr{varname}\n"
193 "%\n"
194 "%If desc is a function, the expression tree is shown.\n"
195 "%Mostly interesting for real expression, i.e., when the\n"
196 "%function body was defined within parenthesis.\n"
197 );
198 TOK_ADD(clear,"x",tok_t::SYSONLY,
199 "%Clear variables\n"
200 "%Syntax: \\clear{partial varname}\n"
201 "%\n"
202 "%Clears all global variables on the current level\n"
203 "%beginning with the partial variable name.\n"
204 );
205
206 //////////////////////////////////////////////////////
207
208 TOK_ADD(exist,"x",tok_t::PUBLIC,
209 "%True if variable exist\n"
210 "%Syntax: \\exist{varname}\n"
211 );
212 TOK_ADD(nexist,"x",tok_t::PUBLIC,
213 "%True if variable does not exist\n"
214 "%Syntax: \\nexist{varname}\n"
215 );
216 TOK_ADD(empty,"x",tok_t::PUBLIC,
217 "%True if variable is empty\n"
218 "%Syntax: \\empty{varname}\n"
219 "%\n"
220 "%Generates an error if varname does not exist.\n"
221 );
222 TOK_ADD(nempty,"x",tok_t::PUBLIC,
223 "%True if variable is non-empty\n"
224 "%Syntax: \\nempty{varname}\n"
225 "%\n"
226 "%Generates an error if varname does not exist.\n"
227 );
228
229 //////////////////////////////////////////////////////
230
231 TOK_ADD(export,"xx",tok_t::SYSONLY,
232 "%Export local variables\n"
233 "%Syntax: \\export{global partial name}{local partial name}\n"
234 "%\n"
235 "%Copies a sequence of local variables, beginning with the\n"
236 "%local partial name, from the same - not nescessarily the current -\n"
237 "%local stack into a set of global variables beginning with\n"
238 "%the global partial name.\n"
239 "%\n"
240 "%Copies all local variables in the current stack if no\n"
241 "%partial name is given.\n"
242 "%\n"
243 "%Copies all variables in the current database record\n"
244 "%if the partial name @ is given.\n"
245 );
246 TOK_ADD(import,"xx",tok_t::SYSONLY,
247 "%Import global variables\n"
248 "%Syntax: \\import{local partial name}{global partial name}\n"
249 "%\n"
250 "%Copies a sequence of global variables, beginning with the\n"
251 "%global partial name, from the same - not nescessarily the\n"
252 "%current - global level into a set of local variables beginning\n"
253 "%with the local partial name.\n"
254 "%\n"
255 "%Copies all global variables on the current level if no\n"
256 "%partial name is given.\n"
257 "%\n"
258 "%Creates a new or updates an existing database record if\n"
259 "%the partial name @ is given.\n"
260 );
261 TOK_ADD(list,"?",tok_t::PUBLIC,
262 "%List local variables\n"
263 "%Syntax: \\list<partial name>\n"
264 "%\n"
265 "%Generates a list of names, beginning with the partial name,\n"
266 "%from the same - not nescessarily the current - local stack.\n"
267 "%\n"
268 "%Generates all local variables in the current stack if no\n"
269 "%partial name is given.\n"
270 "%\n"
271 "%Generates a list of tables if @ is given.\n"
272 );
273 TOK_ADD(globlist,"?",tok_t::PUBLIC,
274 "%List global variables\n"
275 "%Syntax: \\globlist<partial name>\n"
276 "%\n"
277 "%Generates a list of names, beginning with the partial name,\n"
278 "%from the same - not nescessarily the current - global level.\n"
279 "%\n"
280 "%Generates all global variables on the current level if no\n"
281 "%partial name is given.\n"
282 );
283 TOK_ADD(lrec,"xx?",tok_t::PUBLIC,
284 "%Create a local record\n"
285 "%Syntax: \\lrec{partial name}{name list}<init>\n"
286 "%\n"
287 "%Creates a set of local variables, all beginning with the\n"
288 "%partial name, and initializes each variable to init.\n"
289 );
290
291 //////////////////////////////////////////////////////
292
293 TOK_ADD(arg,"x",tok_t::PUBLIC,
294 "%Show/Evaluate argument #n.\n"
295 "%Syntax: \\arg{n}\n"
296 "%\n"
297 "%Same as the command \\1, \\2 etc, except this\n"
298 "%may be used to index the arguments e.g. using local variables.\n"
299 );
300 TOK_ADD(args,"",tok_t::PUBLIC,
301 "%Number of arguments in the current function\n"
302 "%Syntax: \\args\n"
303 "%\n"
304 "%Note that the optional argument will count as one variable,\n"
305 "%and may be accesed using either \\0 or \\arg{\\args}.\n"
306 );
307
308 //////////////////////////////////////////////////////
309
310 TOK_ADD(random,"x",tok_t::PRIVATE,
311 "%Get n random digits between 0 and 9 inclusive\n"
312 "%Syntax: \\random{n}\n"
313 );
314
315}
diff --git a/src/lang/db.cc b/src/lang/db.cc
new file mode 100644
index 0000000..9192d09
--- /dev/null
+++ b/src/lang/db.cc
@@ -0,0 +1,237 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22static dbmap* GetDB(Env& env) throw(merror_t) {
23 if(!env.db) THROW("htc: no open database");
24 return env.db;
25}
26
27static int eval(Env& env,expr_t* x,int mod=OP_ALL) {
28 mswrite out;
29 if(x->status&OP_PARSE) env.parse(out,x->expr); else x->eval(out,env,mod);
30 return atob(out.str());
31}
32
33////////////////////////////////////////////////////////////////////////////
34
35TOK_IMPL(create) {
36 dbref_t* ref=DBRef(*env.toks,env[0],ms_empty,tok_t::PUBLIC,1);
37 ref->db.Open("/dev/zero",1);
38 sref first,rest=env[1]; int n=0;
39 while(Split(first,rest)) ref->db.InsertTable(n++,first);
40 ref->db.Order(env[2],env[3]);
41}
42
43TOK_IMPL(sort) {
44 dbref_t* ref=(dbref_t*)env.toks->get_this(env[0]);
45 if(env.is_clear(ref)&&ref->is_dbref()) {
46 ref->db.remap();
47 ref->db.Sort(env[1],env[2]);
48 }
49 else THROW("htc: "<<env[0]<<" is not a sortable on the current level");
50}
51
52TOK_IMPL(db) {
53 dbref_t* ref=(dbref_t*)env.toks->get(env[0]);
54 if(env.is_clear(ref)&&ref->is_dbref()) {
55 ref->db.remap();
56 Env(env,ref->db).parse(out,env.arg(1));
57 }
58 else THROW("htc: "<<env[0]<<" is not a db reference");
59}
60
61////////////////////////////////////////////////////////////////////////////
62
63TOK_IMPL(query) {
64 dbmap* db=GetDB(env);
65 expr_t* x[2]={env.arg(0),env.arg(1)};
66 Env nenv(env,*db);
67 nenv.dbat=0;
68 while(nenv.dbat>=0&&env.req->is_running()&&nenv.dbat<db->size()) {
69 int size=db->size();
70 if(eval(nenv,x[0],OP_LOCAL)) nenv.parse(out,x[1]);
71 if(db->size()==size) nenv.dbat++;
72 }
73}
74
75TOK_IMPL(find_rec) {
76 dbmap* db=GetDB(env);
77 Env nenv(env,*db);
78 nenv.dbat=db->Find(env[0]);
79 if(nenv.dbat>=0&&nenv.dbat<db->size()) nenv.parse(out,env.arg(1));
80 else env.parg(out,2);
81}
82
83////////////////////////////////////////////////////////////////////
84
85TOK_IMPL(first_rec) { env.dbat=0; }
86TOK_IMPL(prev_rec) { if(env.dbat>0) env.dbat--; }
87TOK_IMPL(next_rec) { if(env.dbat<GetDB(env)->size()) env.dbat++; }
88TOK_IMPL(exist_rec) { out<<bool(env.dbat>=0&&env.dbat<GetDB(env)->size()); }
89
90TOK_IMPL(rem_rec) {
91 dbmap* db=GetDB(env);
92 if(env.dbat>=0&&env.dbat<env.db->size()) db->Rem(env.dbat);
93}
94
95////////////////////////////////////////////////////////////////////
96
97TOK_IMPL(lastkey) {
98 dbmap* db=GetDB(env);
99 if(!db->empty()) out<<db->at(db->size()-1,db->Index());
100}
101
102TOK_IMPL(prevkey) {
103 dbmap* db=GetDB(env);
104 if(env.dbat>0&&env.dbat<=db->size()) out<<db->at(env.dbat-1,db->Index());
105}
106
107TOK_IMPL(nextkey) {
108 dbmap* db=GetDB(env);
109 if(env.dbat>=0&&env.dbat+1<db->size()) out<<db->at(env.dbat+1,db->Index());
110}
111
112TOK_IMPL(qprevkey) {
113 dbmap* db=GetDB(env);
114 expr_t* x=env.arg(0);
115 Env nenv(env,*db);
116 nenv.dbat=env.dbat-1;
117 while(nenv.dbat>=0&&env.req->is_running()&&nenv.dbat<db->size()) {
118 if(eval(nenv,x,OP_LOCAL)) { out<<db->at(nenv.dbat,db->Index()); break; }
119 else nenv.dbat--;
120 }
121}
122
123TOK_IMPL(qnextkey) {
124 dbmap* db=GetDB(env);
125 expr_t* x=env.arg(0);
126 Env nenv(env,*db);
127 nenv.dbat=env.dbat+1;
128 while(nenv.dbat>=0&&env.req->is_running()&&nenv.dbat<db->size()) {
129 if(eval(nenv,x,OP_LOCAL)) { out<<db->at(nenv.dbat,db->Index()); break; }
130 else nenv.dbat++;
131 }
132}
133
134////////////////////////////////////////////////////////////////////
135
136void envAddDB(tokmap& T)
137{
138 TOK_ADD(create,"xxxx",tok_t::SYSONLY,
139 "%Create a new database\n"
140 "%Syntax: \\create{varname}{tables}{index}{comp}\n"
141 "%\n"
142 "%Index is the unique, ordered table.\n"
143 "%Comp is the compare function.\n"
144 "%A maxmimum of 32 tables are allowed in HDB/1.2\n"
145 );
146 TOK_ADD(sort,"xxx",tok_t::PRIVATE,
147 "%Sort a database\n"
148 "%Syntax: \\sort{varname}{index}{comp}\n"
149 "%\n"
150 "%Note that only globals on the current level are sortable.\n"
151 );
152
153 ////////////////////////////////////////////////////////
154
155 TOK_ADD(db,"xr",tok_t::PRIVATE,
156 "%Set current database\n"
157 "%Syntax: \\db{varname}{body}\n"
158 "%\n"
159 "%Within body, all database functions apply.\n"
160 );
161 TOK_ADD(query,"xr",tok_t::PRIVATE,
162 "%Query current database\n"
163 "%Syntax: \\query{test}{body}\n"
164 "%\n"
165 "%Evaluates body for all record where test is true.\n"
166 "%\n"
167 "%optimizes globals; it is ok to use full function\n"
168 "%expressions in the query. Turned out to be better after all.\n"
169 );
170 TOK_ADD(find_rec,"xr?",tok_t::PRIVATE,
171 "%Find record by key, in current database\n"
172 "%Syntax: \\find.rec{key}{body}<else>\n"
173 "%\n"
174 "%Evaluates body if key is found in the current ordering.\n"
175 "%Otherwise, evaluates <else>, if exist.\n"
176 );
177
178 ////////////////////////////////////////////////////////
179
180 TOK_ADD(first_rec,"",tok_t::PRIVATE,
181 "%Go to first record\n"
182 "%Syntax: \\first.rec\n"
183 );
184 TOK_ADD(exist_rec,"",tok_t::PRIVATE,
185 "%True if current record exist\n"
186 "%Syntax: \\exist.rec\n"
187 );
188 TOK_ADD(next_rec,"",tok_t::PRIVATE,
189 "%Go to next record\n"
190 "%Syntax: \\next.rec\n"
191 );
192 TOK_ADD(prev_rec,"",tok_t::PRIVATE,
193 "%Go to previous record\n"
194 "%Syntax: \\prev.rec\n"
195 );
196 TOK_ADD(rem_rec,"",tok_t::SYSONLY,
197 "%Remove current record\n"
198 "%Syntax: \\rem.rec\n"
199 );
200
201 ////////////////////////////////////////////////////////
202
203 TOK_ADD(lastkey,"",tok_t::PRIVATE,
204 "%Last key of current order\n"
205 "%Syntax: \\lastkey\n"
206 "%\n"
207 "%Silently ignored if not found.\n"
208 );
209 TOK_ADD(prevkey,"",tok_t::PRIVATE,
210 "%Previous key of current order\n"
211 "%Syntax: \\prevkey\n"
212 "%\n"
213 "%Silently ignored if not found.\n"
214 );
215 TOK_ADD(nextkey,"",tok_t::PRIVATE,
216 "%Next key of current order\n"
217 "%Syntax: \\nextkey\n"
218 "%\n"
219 "%Silently ignored if not found.\n"
220 );
221
222 ////////////////////////////////////////////////////////
223
224 TOK_ADD(qprevkey,"r",tok_t::PRIVATE,
225 "%Previous key of current order, satisfying query\n"
226 "%Syntax: \\qprevkey\n"
227 "%\n"
228 "%Silently ignored if not found.\n"
229 );
230 TOK_ADD(qnextkey,"r",tok_t::PRIVATE,
231 "%Next key of current order, satisfying query\n"
232 "%Syntax: \\qnextkey\n"
233 "%\n"
234 "%Silently ignored if not found.\n"
235 );
236
237}
diff --git a/src/lang/env.cc b/src/lang/env.cc
new file mode 100644
index 0000000..83f1a7e
--- /dev/null
+++ b/src/lang/env.cc
@@ -0,0 +1,308 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21#include <mt/random.h>
22
23static unsigned long seed=RandomInit(time(0));
24
25mstring Random(int n)
26{
27 mstring s;
28 for(int i=0;i<n;i++) {
29 int digit=int(10*Uniform());
30 if(digit>9) THROW("env: assertion on lib failed");
31 s+=char(48+digit);
32 }
33 return s;
34}
35
36///////////////////////////////////////////////////
37
38void Env::clear_args()
39{
40 for(int i=0;i<xarg.size();i++) delete xarg[i]; xarg.clear();
41 for(int i=0;i<rarg.size();i++) delete rarg[i]; rarg.clear();
42 args=0;
43}
44
45void Env::parg(mstream& out,int n) throw(merror_t)
46{
47 if(args) {
48 if(n<0) n+=args;
49 if(n>=0&&n<args) {
50 if(n<xsize()) out<<xarg[n]->result;
51 else eval(out,rarg[n-xsize()],0);
52 }
53 }
54 else if(up) up->parg(out,n);
55}
56
57void Env::parg(mstring& tmp,int n) throw(merror_t)
58{
59 swrite sw(tmp);
60 parg(sw,n);
61}
62
63mstring Env::parg(int n) throw(merror_t)
64{
65 mswrite tmp; parg(tmp,n); return tmp.str();
66}
67
68//////////////////////////////////////////////////////
69
70int Env::onarg(int n) const
71{
72 if(args) {
73 if(n<0) n+=args;
74 if(n>=0&&n<args) {
75 if(n<xsize()) return xarg[n]->result.nempty();
76 else return rarg[n-xsize()]->expr.nempty();
77 }
78 }
79 else if(up) return up->onarg(n);
80 return 0;
81}
82
83expr_t* Env::arg(int n) throw(merror_t) {
84 if(args) {
85 if(n<0) n+=args;
86 if(n>=0&&n<args) {
87 if(n<xsize()) return xarg[n];
88 else return rarg[n-xsize()];
89 }
90 }
91 else if(up) return up->arg(n);
92 THROW("env: bad arg number "<<n);
93 return 0;
94}
95
96const sref& Env::operator[](int n) const throw(merror_t) {
97 if(args) {
98 if(n<0) n+=args;
99 if(n>=0&&n<args) {
100 if(n<xsize()) return xarg[n]->result;
101 else THROW("env: post-eval expression not readable here");
102 }
103 }
104 else if(up) return up->operator[](n);
105 THROW("env: bad arg number "<<n);
106 return ms_empty;
107}
108
109//////////////////////////////////////////////////////
110
111const sref Env::glob(const sref& t) const throw(merror_t)
112{
113 const tok_t* p=toks->get(t);
114 if(is_clear(p)&&!p->is_runnable()) return p->body;
115 THROW("env: could not find global variable "<<t);
116 return ms_empty;
117}
118
119int Env::glob_find(const sref& t) const
120{
121 const tok_t* p=toks->get(t);
122 return is_clear(p)&&!p->is_runnable();
123}
124
125int Env::onglob(const sref& t) const
126{
127 const tok_t* p=toks->get(t);
128 return is_clear(p)&&!p->is_runnable()&&p->body.nempty();
129}
130
131void Env::glob_list(rpile& list,const sref& t) const
132{
133 list.clear();
134 if(t.empty()) {
135 for(const_iterator p=toks->begin();p!=toks->end();++p) {
136 if(is_clear(*p)&&!(*p)->is_runnable()) list.push_back((*p)->name);
137 }
138 }
139 else {
140 int cont=1;
141 for(const tokmap* tok=toks;tok&&cont;tok=tok->up) {
142 for(const_iterator p=tok->begin();p!=tok->end();++p) {
143 if((*p)->name.left(t.size())==t&&is_clear(*p)&&!(*p)->is_runnable()) {
144 list.push_back((*p)->name);
145 cont=0;
146 }
147 }
148 }
149 }
150}
151
152void Env::glob_adb(const sref& fx,const sref& t) throw(merror_t)
153{
154 if(!db) THROW("htc: no active database");
155 rpile list; glob_list(list,t);
156 mrvec<int> col(list.size());
157 int index=-1;
158 for(int i=0;i<col.size();i++) {
159 col[i]=db->Index(fx+list[i].right(t.size()));
160 if(col[i]==db->Index()) index=i;
161 }
162 if(index<0) THROW("env: index required when adding a db record");
163 int row=db->Find(glob(list[index]));
164 if(row>=0) {
165 for(int i=0;i<list.size();i++) if(i!=index) db->Set(row,col[i],glob(list[i]));
166 }
167 else {
168 spile nlist(db->Tables());
169 for(int i=0;i<list.size();i++) nlist[col[i]]=glob(list[i]);
170 row=db->Insert(nlist,1);
171 }
172 if(row<0) THROW("htc: could not add record - denied");
173 dbat=row;
174}
175
176//////////////////////////////////////////////////////
177
178const sref Env::aloc(const sref& t,const sref& v) throw(merror_t)
179{
180 if(!is_tokname(t)) THROW("env: bad token name "<<t);
181 return loc.add(new tok_t(t,v,tight()),1,1)->body;
182}
183
184const sref Env::sloc(const sref& t,const sref& v) throw(merror_t)
185{
186 if(db) {
187 int p=db->FindIndex(*t=='@'?t.popf():t);
188 if(p>=0) {
189 if(p==db->Index()) THROW("env: cannot assign to db index");
190 if(dbat<0||dbat>=db->size()) THROW("env: not a valid db record");
191 db->Set(dbat,p,v);
192 return db->at(dbat,p);
193 }
194 }
195 return loc.set(new tok_t(t,v,tight()),1,1)->body;
196}
197
198const sref Env::gloc(const sref& t) const throw(merror_t)
199{
200 if(db) {
201 int p=db->FindIndex(*t=='@'?t.popf():t);
202 if(p>=0) {
203 if(dbat>=0&&dbat<db->size()) return db->at(dbat,p);
204 else THROW("env: not a valid database record");
205 }
206 }
207 const tok_t* p=loc.get(t);
208 if(is_clear(p)&&!p->is_runnable()) return p->body;
209 THROW("env: could not find local variable "<<t);
210 return ms_empty;
211}
212
213int Env::gloc_find(const sref& t) const
214{
215 if(db) {
216 int p=db->FindIndex(*t=='@'?t.popf():t);
217 if(p>=0) return dbat>=0&&dbat<db->size();
218 }
219 const tok_t* p=loc.get(t);
220 return is_clear(p)&&!p->is_runnable();
221}
222
223int Env::onloc(const sref& t) const
224{
225 if(db) {
226 int p=db->FindIndex(*t=='@'?t.popf():t);
227 if(p>=0) return dbat>=0&&dbat<db->size()&&db->at(dbat,p).nempty();
228 }
229 const tok_t* p=loc.get(t);
230 return is_clear(p)&&!p->is_runnable()&&p->body.nempty();
231}
232
233void Env::gloc_list(rpile& list,const sref& t) const
234{
235 list.clear();
236 if(t.empty()) {
237 for(const_iterator p=loc.begin();p!=loc.end();++p) {
238 if(is_clear(*p)&&!(*p)->is_runnable()) list.push_back((*p)->name);
239 }
240 }
241 else if(*t=='@') {
242 if(db) {
243 sref tt=t.popf();
244 for(int i=0;i<db->Tables();i++) {
245 if(tt.empty()||db->Table(i).left(tt.size())==tt) list.push_back(db->Table(i));
246 }
247 }
248 else THROW("env: cannot use '@' - no active database");
249 }
250 else {
251 int cont=1;
252 for(const tokmap* tok=&loc;tok&&cont;tok=tok->up) {
253 for(const_iterator p=tok->begin();p!=tok->end();++p) {
254 if((*p)->name.left(t.size())==t&&is_clear(*p)&&!(*p)->is_runnable()) {
255 list.push_back((*p)->name);
256 cont=0;
257 }
258 }
259 }
260 }
261}
262
263void Env::gloc_adb(const sref& fx,const sref& t) throw(merror_t)
264{
265 if(!db) THROW("htc: no active database");
266 rpile list; gloc_list(list,t);
267 mrvec<int> col(list.size());
268 int index=-1;
269 for(int i=0;i<col.size();i++) {
270 col[i]=db->Index(fx+list[i].right(t.size()));
271 if(col[i]==db->Index()) index=i;
272 }
273 if(index<0) THROW("env: index required when adding a db record");
274 int row=db->Find(gloc(list[index]));
275 if(row>=0) {
276 for(int i=0;i<list.size();i++) if(i!=index) db->Set(row,col[i],gloc(list[i]));
277 }
278 else {
279 spile nlist(db->Tables());
280 for(int i=0;i<list.size();i++) nlist[col[i]]=gloc(list[i]);
281 row=db->Insert(nlist,1);
282 }
283 if(row<0) THROW("htc: could not add record - denied");
284 dbat=row;
285}
286
287//////////////////////////////////////////////////////
288
289const mstring sback="../",sident="./",sdots="..",sslash="//";
290
291mstring Env::URI(const sref& raw)
292{
293 int s; mstring cwd=pwd.left_last('/'),uri=raw;
294 while(uri.left(sback.size())==sback) {
295 uri.erase(0,sback.size());
296 cwd=cwd.left_last('/');
297 }
298 while((s=uri.find(sback))>=0) {
299 mstring tmp=uri.left(s).left_last('/').leftand_last('/');
300 tmp+=uri.right(s+sback.size());
301 uri=tmp;
302 }
303 while((s=uri.find(sdots))>=0) uri.erase(s,sdots.size());
304 while((s=uri.find(sident))>=0) uri.erase(s,sident.size());
305 while((s=uri.find(sslash))>=0) uri.erase(s,sslash.size());
306 if(*uri=='/') return uri;
307 else { cwd+='/'; cwd+=uri; return cwd; }
308}
diff --git a/src/lang/env.h b/src/lang/env.h
new file mode 100644
index 0000000..1313d18
--- /dev/null
+++ b/src/lang/env.h
@@ -0,0 +1,156 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef ENVH
21#define ENVH
22
23#include <lang/token.h>
24
25mstring Random(int n);
26
27const int OP_PARSE=8;
28const mstring para_def="\n";
29
30////////////////////////////////////////////////////////////////////
31
32struct Lang {
33 volatile int running;
34 opmap ops;
35 tokmap toks;
36 Lang();
37 virtual ~Lang() {}
38};
39
40struct req_env {
41 Lang* glob;
42 tokmap toks;
43 mstring uri;
44 int lang;
45 volatile int* running;
46
47 int is_running() const { return glob->running&&(!running||*running); }
48
49 req_env(Lang& g,tokmap& p) : glob(&g),toks(p),uri(),lang(0),running(0) {}
50 virtual ~req_env() {}
51};
52
53////////////////////////////////////////////////////////////////////
54
55struct Env : public op_env {
56 typedef mrvec<expr_t*> xpile;
57 typedef tokmap::iterator iterator;
58 typedef tokmap::const_iterator const_iterator;
59
60 Env(opmap& op,req_env& r,unsigned m):
61 op_env(op),req(&r),toks(&r.toks),up(0),mod(m),
62 loc(),db(0),dbat(0),pwd(r.uri),para(para_def),args(0) {}
63
64 Env(Env& p,tokmap& tok,const sref& cwd):
65 op_env(p),req(p.req),toks(&tok),up(p.up),mod(p.mod),
66 loc(p.loc),db(0),dbat(0),pwd(cwd),para(p.para),args(0) {}
67 Env(Env& p,unsigned m,const sref& cwd):
68 op_env(p),req(p.req),toks(p.toks),up(p.up),mod(m),
69 loc(p.loc),db(0),dbat(0),pwd(cwd),para(p.para),args(0) {}
70
71 Env(Env& p):
72 op_env(p),req(p.req),toks(p.toks),up(p.up),mod(p.mod),
73 loc(p.loc),db(p.db),dbat(p.dbat),pwd(p.pwd),para(p.para),args(0) {}
74 Env(Env& p,dbmap& dbm):
75 op_env(p),req(p.req),toks(p.toks),up(p.up),mod(p.mod),
76 loc(p.loc),db(&dbm),dbat(0),pwd(p.pwd),para(p.para),args(0) {}
77 Env(Env& p,opmap& op):
78 op_env(op),req(p.req),toks(p.toks),up(p.up),mod(p.mod),
79 loc(p.loc),db(p.db),dbat(p.dbat),pwd(p.pwd),para(p.para),args(0) {}
80
81 ~Env() { clear_args(); }
82
83 int is_clear(const tok_t* tok) const { return tok&&tok->is_clear(mod); }
84 unsigned tight() const { return tok_t::tight(mod); }
85
86 int check_arg(const runnable_t& ftok) const;
87 int is_arg(const sref& t) const { return cset_digit.test(t.front()); }
88
89 int xsize() const { return xarg.size(); }
90 int rsize() const { return rarg.size(); }
91
92 void xpush(const sref& in) throw(merror_t);
93 void rpush(const sref& in) throw(merror_t);
94 void clear_args();
95
96 void parg(mstream& out,int n) throw(merror_t);
97 void parg(mstring& buf,int n) throw(merror_t);
98 mstring parg(int n) throw(merror_t);
99
100 const sref& operator[](int m) const throw(merror_t);
101 expr_t* arg(int m) throw(merror_t);
102
103 const sref glob(const sref& t) const throw(merror_t);
104
105 int glob_find(const sref& t) const;
106 void glob_list(rpile& list,const sref& t) const;
107 void glob_adb(const sref& fx,const sref& t) throw(merror_t);
108
109 const sref aloc(const sref& t,const sref& v) throw(merror_t);
110 const sref sloc(const sref& t,const sref& v) throw(merror_t);
111 const sref gloc(const sref& t) const throw(merror_t);
112
113 int gloc_find(const sref& t) const;
114 void gloc_list(rpile& list,const sref& t) const;
115 void gloc_adb(const sref& fx,const sref& t) throw(merror_t);
116
117 int onarg(int m) const;
118 int onglob(const sref& s) const;
119 int onloc(const sref& s) const;
120
121 void parse(mstream& out,const sref& in) throw(merror_t);
122 void expr(mstream& out,const sref& in) throw(merror_t);
123 void parse(mstream& out,expr_t* x) throw(merror_t);
124
125 void eval(mstream& out,const sref& in,int child) throw(merror_t);
126 void eval(mstream& out,expr_t* x,int child) throw(merror_t);
127 void eval(mstream& out,runnable_t* ftok,int child) throw(merror_t);
128
129 int split(sref& first,sref& rest) throw(merror_t);
130 void term(mstream& out,expr_t* x) throw(merror_t);
131
132 mstring URI(const sref& raw);
133
134 Env *up;
135 req_env* req;
136 tokmap* toks;
137 int mod,dbat;
138 tokmap loc;
139 dbmap* db;
140 mstring pwd,para,epilog;
141 int args;
142 xpile xarg,rarg;
143};
144
145/////////////////////////////////////////////////////////////////////
146
147struct latex_env : public Env {
148 latex_env(Env& p);
149
150 int split(sref& first,sref& rest) throw(merror_t);
151 void term(mstream& out,expr_t* x) throw(merror_t);
152};
153
154/////////////////////////////////////////////////////////////////////
155
156#endif
diff --git a/src/lang/flow.cc b/src/lang/flow.cc
new file mode 100644
index 0000000..c7c70a0
--- /dev/null
+++ b/src/lang/flow.cc
@@ -0,0 +1,198 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21#include <mt/dates.h>
22using namespace std;
23
24TOK_IMPL(branch) {
25 int index=atoi(env[0]);
26 if(index<0) index+=env.args;
27 if(index>0&&index<env.args) env.parg(out,index);
28 else if(index<0||index>=env.args) THROW("htc: bad branching index "<<index);
29}
30
31TOK_IMPL(if) {
32 if(atob(env[0])) env.parg(out,1); else env.parg(out,2);
33}
34
35TOK_IMPL(nif) {
36 if(!atob(env[0])) env.parg(out,1); else env.parg(out,2);
37}
38
39TOK_IMPL(switch) {
40 sref s=env[0];
41 int i;
42 for(i=1;i+1<env.args;i+=2) if(env.parg(i)==s) { env.parg(out,i+1); return; }
43 if(i<env.args) env.parg(out,i);
44}
45
46/////////////////////////////////////////////////////////////////////
47
48static int eval(Env& env,expr_t* x,int mod) {
49 mswrite out;
50 if(x->status&OP_PARSE) env.parse(out,x->expr); else x->eval(out,env,mod);
51 return atob(out.str());
52}
53
54TOK_IMPL(for) {
55 expr_t* x[4]={env.arg(0),env.arg(1),env.arg(2),env.arg(3)};
56 Env nenv(env);
57 for(eval(nenv,x[0],OP_ALL);
58 env.req->is_running()&&eval(nenv,x[1],OP_LOCAL);
59 eval(nenv,x[2],OP_LOCAL))
60 nenv.parse(out,x[3]);
61}
62
63TOK_IMPL(while) {
64 expr_t* x[2]={env.arg(0),env.arg(1)};
65 Env nenv(env);
66 while(env.req->is_running()&&eval(nenv,x[0],OP_ALL)) nenv.parse(out,x[1]);
67}
68
69/////////////////////////////////////////////////////////////////////
70
71TOK_IMPL(forall) {
72 mstring sep; env.parg(sep,-1);
73 sref s=env[0];
74 sref p,e=env[1];
75 expr_t* x=env.arg(2);
76 Env nenv(env);
77 if(sep.nempty()) {
78 charset seps(sep.c_str());
79 while(Split(p,e,seps)) {
80 nenv.aloc(s,p);
81 nenv.parse(out,x);
82 }
83 }
84 else {
85 while(Split(p,e)) {
86 nenv.aloc(s,p);
87 nenv.parse(out,x);
88 }
89 }
90}
91
92/////////////////////////////////////////////////////////////////////
93
94TOK_IMPL(on_arg) {
95 if(env.up&&env.up->onarg(atoi(env[0])-1)) env.parg(out,1); else env.parg(out,2);
96}
97TOK_IMPL(on_glob) { if(env.onglob(env[0])) env.parg(out,1); else env.parg(out,2); }
98TOK_IMPL(on_loc) { if(env.onloc(env[0])) env.parg(out,1); else env.parg(out,2); }
99
100/////////////////////////////////////////////////////////////////////
101
102TOK_IMPL(setlang) {
103 env.req->lang=Language(env[0]); if(env.req->lang<0) env.req->lang=0;
104}
105
106TOK_IMPL(lang) {
107 env.parg(out,env.req->lang);
108}
109
110/////////////////////////////////////////////////////////////////////
111
112void envAddFlow(tokmap& T)
113{
114 TOK_ADD(branch,"x*",tok_t::PUBLIC,
115 "%Multiple branch\n"
116 "%Syntax: \\branch{x}<body>..<body>\n"
117 "%\n"
118 "%x==0 means nothing is executed, the first body for x==1, etc\n"
119 "%Negative values wrap to end\n"
120 );
121 TOK_ADD(if,"xr?",tok_t::PUBLIC,
122 "%if - logical branch\n"
123 "%Syntax: \\if{x}{body}<else>\n"
124 "%\n"
125 "%if x is non-zero, evaluates body, otherwise else if exist\n"
126 );
127 TOK_ADD(nif,"xr?",tok_t::PUBLIC,
128 "%nif - logical branch\n"
129 "%Syntax: \\nif{x}{body}<else>\n"
130 "%\n"
131 "%if x is zero, evaluates body, otherwise else if exist\n"
132 );
133 TOK_ADD(switch,"x*",tok_t::PUBLIC,
134 "%Multiple switch\n"
135 "%Syntax: \\switch{x}<val><body>..<val><body>..<default>\n"
136 "%\n"
137 "%A sequence of pairs <val><body> follows x\n"
138 "%x==val means body is executed\n"
139 "%\n"
140 "%An unpaired body at the end is treated as default\n"
141 );
142
143 /////////////////////////////////////////////////////////////////////
144
145 TOK_ADD(for,"rrrr",tok_t::PRIVATE,
146 "%C style\n"
147 "%Syntax: \\for{start}{test}{next}{body}\n"
148 "%\n"
149 "%Note that test and next are evaluated with optimization: only\n"
150 "%local variables are updated. Hence, you cannot use a function\n"
151 "%as the whole test, only as a part of the test, as in i<\\function.\n"
152 );
153 TOK_ADD(while,"rr",tok_t::PRIVATE,
154 "%C style\n"
155 "%Syntax: \\while{test}{body}\n"
156 "%\n"
157 "%There is no optimization on test - globals are re-evaluated in each step\n"
158 );
159 TOK_ADD(forall,"xx?r",tok_t::PUBLIC,
160 "%Loop through elements\n"
161 "%Syntax: \\forall{varname}{list}<additional whitespace>{body}\n"
162 "%\n"
163 "%Default whitespace are ( \\t\\r\\n). Optional whitespace characters\n"
164 "%may be given. This enables the design of special lists.\n"
165 );
166
167 /////////////////////////////////////////////////////////////////////
168
169 TOK_ADD(on_arg,"xr?",tok_t::PUBLIC,
170 "%Do if arg exist and is non-empty\n"
171 "%Syntax: \\on.arg{number}{body}<else>\n"
172 );
173 TOK_ADD(on_glob,"xr?",tok_t::PUBLIC,
174 "%Do if global variable exist and is non-empty\n"
175 "%Syntax: \\on.glob{varname}{body}<else>\n"
176 );
177 TOK_ADD(on_loc,"xr?",tok_t::PUBLIC,
178 "%Do if local variable exist and is non-empty\n"
179 "%Syntax: \\on.loc{varname}{body}<else>\n"
180 );
181
182 /////////////////////////////////////////////////////////////////////
183
184 TOK_ADD(lang,"r*",tok_t::PUBLIC,
185 "%Branch on global language\n"
186 "%Syntax: \\lang{en}{sv}..\n"
187 "%\n"
188 "%Currently English (en) and Swedish (sv) are supported\n"
189 );
190 TOK_ADD(setlang,"x",tok_t::PUBLIC,
191 "%Set global language\n"
192 "%Syntax: \\setlang{language code list}\n"
193 "%\n"
194 "%The language actually set is a negotitation -\n"
195 "%the first code in the list recognized is set.\n"
196 "%If not found, the default language English (en) is set.\n"
197 );
198}
diff --git a/src/lang/func.cc b/src/lang/func.cc
new file mode 100644
index 0000000..98cc04c
--- /dev/null
+++ b/src/lang/func.cc
@@ -0,0 +1,249 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21#include <unistd.h>
22
23const mstring cron_tag="cron.";
24const int SSECS=4;
25
26TOK_IMPL(def) {
27 expr_t* x=env.arg(2);
28 func_t* tok=Func(*env.toks,env[0],x->expr,tok_t::PUBLIC,env[1]);
29 if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env);
30}
31
32TOK_IMPL(redef) {
33 expr_t* x=env.arg(2);
34 func_t* tok=Func(*env.toks,env[0],x->expr,tok_t::PUBLIC,env[1],1);
35 if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env);
36}
37
38TOK_IMPL(ldef) {
39 if(env.toks->get(env[0])) THROW("htc: local function would override global token");
40 expr_t* x=env.arg(2);
41 func_t* tok=Func(env.loc,env[0],x->expr,tok_t::PUBLIC,env[1]);
42 if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env);
43}
44
45TOK_IMPL(cron) {
46 mstring name=cron_tag+env[0];
47 expr_t* x=env.arg(1);
48 cron_t* tok=Cron(*env.toks,name,x->expr,tok_t::PUBLIC,atoi(env[0]));
49 if(x->status&OP_PARSE) tok->x.status=OP_PARSE; else tok->x.expand(env);
50}
51
52///////////////////////////////////////////////////
53
54static void Run(tokmap& m,mstream& out,Env& env,const sref& s) throw(merror_t) {
55 tok_t* p=m.get(s);
56 if(!p) THROW("htc: cannot run "<<s<<"; does not exist");
57 try {
58 if(p->is_reference()) env.parse(out,((reference_t*)p)->data);
59 else if(!p->is_runnable()) env.parse(out,p->body);
60 }
61 catch(const merror_t& e) {
62 out<<e.desc;
63 }
64}
65
66TOK_IMPL(run) {
67 Env e(env,env.mod,env.pwd);
68 Run(*env.toks,out,e,env[0]);
69}
70TOK_IMPL(run_private) {
71 Env e(env,XPRIVATE,env.pwd);
72 Run(*env.toks,out,e,env[0]);
73}
74TOK_IMPL(run_public) {
75 Env e(env,XPUBLIC,env.pwd);
76 Run(*env.toks,out,e,env[0]);
77}
78TOK_IMPL(run_local) {
79 try {
80 Env e(env,XPUBLIC,env.pwd);
81 e.parse(out,env.gloc(env[0]));
82 }
83 catch(const merror_t& e) {
84 out<<e.desc;
85 }
86}
87TOK_IMPL(run_cron) {
88 mrvec<cron_t*> cron;
89 int cont=1; for(tokmap* tok=env.toks;tok&&cont;tok=tok->up) {
90 for(Env::iterator p=tok->begin();p!=tok->end();++p) {
91 if((*p)->name.left(cron_tag.size())==cron_tag&&(*p)->is_cron()) {
92 cron.push_back((cron_t*)(*p));
93 cont=0;
94 }
95 }
96 }
97 while(env.req->is_running()&&cron.size()) {
98 int cont=1;
99 for(int i=0;i<cron.size()&&cont;i++) {
100 if(time(0)>cron[i]->last+cron[i]->interval) {
101 mstream ms;
102 env.eval(ms,&cron[i]->x,0);
103 cron[i]->last=time(0);
104 cont=0;
105 }
106 }
107 if(cont) sleep(SSECS);
108 }
109}
110
111//////////////////////////////////////////////////////
112
113void envAddFunc(tokmap& T)
114{
115 TOK_ADD(def,"xxr",tok_t::PUBLIC,
116 "%Define new global function\n"
117 "%Syntax: \\def{varname}{argument string [xr?*]}{body}\n"
118 "%\n"
119 "%The argument string is a sequence of characters describing\n"
120 "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n"
121 "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n"
122 "%The can be only one optional (?) argument.\n"
123 "%The body contains the function body. The arguments are retrieved\n"
124 "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n"
125 "%regardless of where it stands in the sequence.\n"
126 "%\n"
127 "%Generates an error if already defined.\n"
128 );
129 TOK_ADD(redef,"xxr",tok_t::PRIVATE,
130 "%Redefine global function\n"
131 "%Syntax: \\def{varname}{argument string [xr?*]}{body}\n"
132 "%\n"
133 "%The argument string is a sequence of characters describing\n"
134 "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n"
135 "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n"
136 "%The can be only one optional (?) argument.\n"
137 "%The body contains the function body. The arguments are retrieved\n"
138 "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n"
139 "%regardless of where it stands in the sequence.\n"
140 "%\n"
141 "%Takes precedence over any existing function.\n"
142 );
143 TOK_ADD(ldef,"xxr",tok_t::PUBLIC,
144 "%Define a local function\n"
145 "%Syntax: \\ldef{varname}{argument string [xr?*]}{body}\n"
146 "%\n"
147 "%The argument string is a sequence of characters describing\n"
148 "%the argument type, which is one of x (pre-evaluate), r (post-evaluate),\n"
149 "%? (optional post-evaluate) or * (optional at end, post-evaluate).\n"
150 "%The can be only one optional (?) argument.\n"
151 "%The body contains the function body. The arguments are retrieved\n"
152 "%as \\1, \\2 etc, except the optional argument which is retrieved as \\0,\n"
153 "%regardless of where it stands in the sequence.\n"
154 "%\n"
155 "%Local functions work just like global functions, but are only\n"
156 "%accessible from within the current stack frame.\n"
157 );
158 TOK_ADD(cron,"xr",tok_t::SYSONLY,
159 "%Define a cron function\n"
160 "%Syntax: \\cron{interval}{body}\n"
161 "%\n"
162 "%A cron function is executed every interval seconds,\n"
163 "%when running in cron mode.\n"
164 "%\n"
165 "%See \\run.cron.\n"
166 );
167
168 //////////////////////////////////////////////////////
169
170 TOK_ADD(run,"x",tok_t::SYSONLY,
171 "%Evaluate the body of variable in current running mode\n"
172 "%Syntax: \\run{varname}\n"
173 "%\n"
174 "%The running modes are:\n"
175 "%\n"
176 "%XINIT Init mode is only used to collect meta information\n"
177 "%XSYSTEM The system mode - everything is accessible\n"
178 "%XPRIVATE Private mode - suitable for in-door custom programs\n"
179 "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n"
180 "% via the web. This is the default mode for all derivative\n"
181 "% functions, as well as for globals and constants.\n"
182 "%\n"
183 "%IT IS A MAJOR SECURITY HAZARD TO EVALUATE UNKNOWN\n"
184 "%VARIABLES IN XSYSTEM MODE!!\n"
185 "%\n"
186 "%If at all, user-supplied information should only be run\n"
187 "%in public mode, for instance to allow the expansion of latex\n"
188 "%commands. NEVER use this mode outside the core.\n"
189 );
190 TOK_ADD(run_private,"x",tok_t::SYSONLY,
191 "%Evaluate the body of variable in private mode\n"
192 "%Syntax: \\run.private{varname}\n"
193 "%\n"
194 "%The running modes are:\n"
195 "%\n"
196 "%XINIT Init mode is only used to collect meta information\n"
197 "%XSYSONLY The system mode - everything is accessible\n"
198 "%XPRIVATE Private mode - suitable for in-door custom htc code\n"
199 "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n"
200 "% via the web. This is the default mode for all derivative\n"
201 "% functions, as well as for globals and constants.\n"
202 "%\n"
203 "%The execution of sysonly functions is silent, just as it wasn't there.\n"
204 );
205 TOK_ADD(run_public,"x",tok_t::PRIVATE,
206 "%Evaluate the body of variable in public mode\n"
207 "%Syntax: \\run.public{varname}\n"
208 "%\n"
209 "%The running modes are:\n"
210 "%\n"
211 "%XINIT Init mode is only used to collect meta information\n"
212 "%XSYSONLY The system mode - everything is accessible\n"
213 "%XPRIVATE Private mode - suitable for in-door custom programs\n"
214 "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n"
215 "% via the web. This is the default mode for all derivative\n"
216 "% functions, as well as for globals and constants.\n"
217 "%\n"
218 "%The execution of sysonly or private functions is silent,\n"
219 "%just as they weren't there.\n"
220 );
221 TOK_ADD(run_local,"x",tok_t::PRIVATE,
222 "%Evaluate the body of the local variable in public mode\n"
223 "%Syntax: \\run.local{varname}\n"
224 "%\n"
225 "%The running modes are:\n"
226 "%\n"
227 "%XINIT Init mode is only used to collect meta information\n"
228 "%XSYSTEM The system mode - everything is accessible\n"
229 "%XPRIVATE Private mode - suitable for in-door custom programs\n"
230 "%XPUBLIC Public mode - quite restrictive, may be run by anyone\n"
231 "% via the web. This is the default mode for all derivative\n"
232 "% functions, as well as for globals and constants.\n"
233 "%\n"
234 "%The execution of sysonly or private functions is silent,\n"
235 "%just as they weren't there.\n"
236 );
237 TOK_ADD(run_cron,"",tok_t::SYSONLY,
238 "%Go into an infinite loop and run the crontab command.\n"
239 "%Syntax: \\run.cron{}\n"
240 "%\n"
241 "%Note that only cron functions from the highest global level\n"
242 "%where a cron function is defined is run. Hence you may redefine\n"
243 "%earlier crontabs, but cannot mix between levels.\n"
244 "%\n"
245 "%You can only have one crontab of a certain interval.\n"
246 "%\n"
247 "%Produces no output.\n"
248 );
249}
diff --git a/src/lang/help.cc b/src/lang/help.cc
new file mode 100644
index 0000000..750a13a
--- /dev/null
+++ b/src/lang/help.cc
@@ -0,0 +1,140 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22TOK_IMPL(help) {
23 out<<"HTC/1.2 - HyperText Compiler (H. Rydberg (C) 1998,1999,2000,2001)\n";
24 out<<"\n";
25 out<<"Try these commands:\n";
26 out<<"\\help - This message\n";
27 out<<"\\ops - List all operators\n";
28 out<<"\\ops{op} - Get info on operator\n";
29 out<<"\\tok - List all tokens\n";
30 out<<"\\tok{tok} - Get info on token\n";
31 out<<"\\src{tok} - View token source\n";
32}
33
34TOK_IMPL(ops) {
35 mstring cmd; env.parg(cmd,-1);
36 if(cmd.nempty()) {
37 out<<cmd<<"\n";
38 const op_t* p=env.ops->get(cmd);
39 if(p) {
40 if(p->pre1) out<<"Unary operator, precedence "<<p->pre1<<"\n";
41 if(p->pre2) out<<"Binary operator, precedence "<<p->pre2<<"\n";
42 out<<"\n";
43 out<<p->desc;
44 }
45 else {
46 out<<"(not found)\n";
47 }
48 }
49 else {
50 mstring line;
51 line.convert("%-3s %-3s %s\n","P1","P2","NAME");
52 out<<line;
53 for(opmap::iterator p=env.ops->begin();p!=env.ops->end();p++) {
54 line.convert("%-3d %-3d %s\n",(*p)->pre1,(*p)->pre2,(*p)->name.c_str());
55 out<<line;
56 }
57 }
58}
59
60TOK_IMPL(tok) {
61 mstring cmd; env.parg(cmd,-1);
62 if(cmd.nempty()) {
63 out<<cmd<<"\n";
64 const tok_t* p=env.toks->get(cmd);
65 if(p) {
66 out<<"Mode: "<<Mode(*p)<<"\n";
67 if(p->mod&tok_t::RESTRICT) out<<"public ";
68 else if(p->mod&tok_t::NORMAL) out<<"normal ";
69 else if(p->mod&tok_t::SYSONLY) out<<"system ";
70 else if(p->mod&tok_t::INIT) out<<"init ";
71 if(p->is_runnable()) {
72 if(p->is_binary()) out<<"built-in ";
73 out<<"function\n";
74 }
75 else {
76 if(p->is_const()) out<<"constant"; else out<<"variable";
77 if(p->is_reference()) out<<" reference";
78 if(p->is_dbref()) out<<" database reference";
79 out<<"\n";
80 }
81 out<<"Usage: ";
82 if(p->is_runnable()) out<<*(func_t*)p; else out<<"\\"<<p->name;
83 out<<"\n";
84 if(p->is_runnable()) {
85 mstring desc=Desc(*p);
86 if(desc.nempty()) { out<<"\n"; out<<desc; }
87 }
88 }
89 else {
90 out<<"(not found)\n";
91 }
92 }
93 else {
94 mstring line;
95 int n=0;
96 for(tokmap* tok=env.toks;tok;tok=tok->up) {
97 line.convert("%-12s %s %d\n","MODE","NAME LEVEL",n);
98 out<<line;
99 for(tokmap::iterator p=tok->begin();p!=tok->end();p++) {
100 line.convert("%s %s\n",Mode(*(*p)).c_str(),(*p)->name.c_str());
101 out<<line;
102 }
103 n--;
104 }
105 }
106}
107
108TOK_IMPL(src) {
109 const tok_t* p=env.toks->get(env[0]);
110 if(!p) out<<env[0]<<" (not found)\n";
111 else {
112 if(p->is_runnable()) {
113 const func_t* ftok=(func_t*)p;
114 out<<"{"<<ftok->name<<"}{"<<ftok->arg<<"}";
115 if(p->is_binary()) out<<" (built-in function)\n";
116 else out<<"{"<<ftok->x.expr<<"}\n";
117 }
118 else out<<env[0]<<" (not a function)\n";
119 }
120}
121
122void envAddHelp(tokmap& T)
123{
124 TOK_ADD(help,"",tok_t::PRIVATE,
125 "%Help message\n"
126 "%Syntax: \\help\n"
127 );
128 TOK_ADD(ops,"?",tok_t::PRIVATE,
129 "%Help on operators\n"
130 "%Syntax: \\ops<opname>\n"
131 );
132 TOK_ADD(tok,"?",tok_t::PRIVATE,
133 "%Help on tokens\n"
134 "%Syntax: \\tok<tokname>\n"
135 );
136 TOK_ADD(src,"x",tok_t::SYSONLY,
137 "%Source of token\n"
138 "%Syntax: \\src{tokname}\n"
139 );
140}
diff --git a/src/lang/lang.cc b/src/lang/lang.cc
new file mode 100644
index 0000000..28e56f3
--- /dev/null
+++ b/src/lang/lang.cc
@@ -0,0 +1,39 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22void envAddOps(opmap& M,tokmap& T);
23void envAddBasic(tokmap& T);
24void envAddFunc(tokmap& T);
25void envAddFlow(tokmap& T);
26void envAddDB(tokmap& T);
27void envAddLatex(tokmap& T);
28void envAddHelp(tokmap& T);
29
30Lang::Lang() : running(1)
31{
32 envAddOps(ops,toks);
33 envAddBasic(toks);
34 envAddFunc(toks);
35 envAddFlow(toks);
36 envAddDB(toks);
37 envAddLatex(toks);
38 envAddHelp(toks);
39}
diff --git a/src/lang/latex.cc b/src/lang/latex.cc
new file mode 100644
index 0000000..d423230
--- /dev/null
+++ b/src/lang/latex.cc
@@ -0,0 +1,152 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21using namespace std;
22
23static opmap op_latex;
24
25latex_env::latex_env(Env& p) : Env(p) { ops=&op_latex; }
26
27//////////////////////////////////////////////////////
28
29TOK_IMPL(it) {
30 mstring s; env.parg(s,-1);
31 if(s.nempty()) { out<<"<i>"; out<<s.right_first_not_of(cset_ws); out<<"</i>"; }
32 else { out<<"<i>"; env.epilog=sref("</i>")+env.epilog; }
33}
34
35TOK_IMPL(em) {
36 mstring s; env.parg(s,-1);
37 if(s.nempty()) { out<<"<em>"; out<<s.right_first_not_of(cset_ws); out<<"</em>"; }
38 else { out<<"<em>"; env.epilog=sref("</em>")+env.epilog; }
39}
40
41TOK_IMPL(bf) {
42 mstring s; env.parg(s,-1);
43 if(s.nempty()) { out<<"<b>"; out<<s.right_first_not_of(cset_ws); out<<"</b>"; }
44 else { out<<"<b>"; env.epilog=sref("</b>")+env.epilog; }
45}
46
47TOK_IMPL(mathbf) {
48 mstring s; env.parg(s,-1);
49 if(s.nempty()) { out<<"<b>"; out<<s.right_first_not_of(cset_ws); out<<"</b>"; }
50 else { out<<"<b>"; env.epilog=sref("</b>")+env.epilog; }
51}
52
53TOK_IMPL(rm) {
54 mstring s; env.parg(s,-1);
55 if(s.nempty()) { out<<s.right_first_not_of(cset_ws); }
56}
57
58//////////////////////////////////////////////////////////
59
60TOK_IMPL(setpara) {
61 env.para=env[0];
62}
63
64TOK_IMPL(epilog) {
65 env.epilog=env[0]+env.epilog;
66}
67
68//////////////////////////////////////////////////////////
69
70TOK_IMPL(equation) {
71 out<<env.para;
72 latex_env(env).expr(out,env.arg(0)->expr);
73 out<<env.para;
74}
75
76//////////////////////////////////////////////////////////
77
78void envAddLatex(tokmap& T)
79{
80 static int init; if(!init) { init=1; opAddLatex(op_latex); }
81
82 //////////////////////////////////////////////////////////
83
84 TOK_ADD(it,"?",tok_t::PUBLIC,
85 "%Set Italics mode\n"
86 "%Syntax: \\it<body>\n"
87 "%\n"
88 "%Note that the body is optional, just like in latex.\n"
89 );
90 TOK_ADD(em,"?",tok_t::PUBLIC,
91 "%Set emph mode\n"
92 "%Syntax: \\em<body>\n"
93 "%\n"
94 "%Note that the body is optional, just like in latex.\n"
95 );
96 TOK_ADD(bf,"?",tok_t::PUBLIC,
97 "%Set Boldface mode\n"
98 "%Syntax: \\bf<body>\n"
99 "%\n"
100 "%Note that the body is optional, just like in latex.\n"
101 );
102 TOK_ADD(mathbf,"?",tok_t::PUBLIC,
103 "%Set Math boldface mode\n"
104 "%Syntax: \\mathbf<body>\n"
105 "%\n"
106 "%Note that the body is optional, just like in latex.\n"
107 );
108 TOK_ADD(rm,"?",tok_t::PUBLIC,
109 "%Set rm face mode\n"
110 "%Syntax: \\rm<body>\n"
111 "%\n"
112 "%Note that the body is optional, just like in latex.\n"
113 );
114
115 //////////////////////////////////////////////////////////
116
117 TOK_ADD(setpara,"x",tok_t::PUBLIC,
118 "%Set paragraph string\n"
119 "%Syntax: \\setpara{string}\n"
120 "%\n"
121 "%Whenever a series of newlines is encountered, it is\n"
122 "%replaced by this string. The default is a newline.\n"
123 "%\n"
124 "%Operates on stack level (may be nested)\n"
125 );
126 TOK_ADD(epilog,"x",tok_t::PUBLIC,
127 "%Add string to the epilog\n"
128 "%Syntax: \\epilog{string}\n"
129 "%\n"
130 "%The epilog string is output when the current stack frame\n"
131 "%goes out of scope. For functions like \\bf, which needs\n"
132 "%an end tag to be inserted at the right place.\n"
133 "%\n"
134 "%Operates on stack level (may be nested)\n"
135 );
136
137 //////////////////////////////////////////////////////////
138
139 TOK_ADD(equation,"r",tok_t::PUBLIC,
140 "%Evaluate equation (LaTeX)\n"
141 "%Syntax: \\equation{body}\n"
142 );
143
144 //////////////////////////////////////////////////////////
145
146 Const(T,sref("t"),sref("\t"),tok_t::PUBLIC);
147 Const(T,sref("n"),sref("\n"),tok_t::PUBLIC);
148 Const(T,sref("f"),sref("\f"),tok_t::PUBLIC);
149
150 //////////////////////////////////////////////////////////
151}
152
diff --git a/src/lang/ops.cc b/src/lang/ops.cc
new file mode 100644
index 0000000..7916d96
--- /dev/null
+++ b/src/lang/ops.cc
@@ -0,0 +1,150 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22//////////////////////////////////////////////////////
23
24struct xop_t : public op_t {
25 typedef void (*xop1_t)(mstream&,Env&,const sref&);
26 typedef void (*xop2_t)(mstream&,Env&,const sref&,const sref&);
27 xop_t(const mstring& s,int p1,int p2,int l,int r,
28 xop1_t op1,xop2_t op2,const mstring& d):
29 op_t(s,p1,p2,l,r,(op1_t)op1,(op2_t)op2,d) {}
30};
31
32//////////////////////////////////////////////////////
33
34#define X1_IMPL(name) \
35static void impl_##name(mstream& out,Env& env,const sref& a) throw(merror_t)
36#define X2_IMPL(name) \
37static void impl_##name(mstream& out,Env& env,const sref& L,const sref& R) throw(merror_t)
38
39#define X1_ADDN(p,l,r,f,n,d) M.add(new xop_t(#n,p,0,l,r,impl_##f,0,d))
40#define X2_ADDN(p,l,r,f,n,d) M.add(new xop_t(#n,0,p,l,r,0,impl_##f,d))
41
42//////////////////////////////////////////////////////
43
44X1_IMPL(exist) {
45 mstring name;
46 swrite sw(name);
47 env.eval(sw,a,0);
48 out<<env.gloc_find(name);
49}
50
51X2_IMPL(new) {
52 mstring name;
53 swrite sw(name);
54 env.eval(sw,L,0);
55 env.aloc(name,R);
56}
57
58X2_IMPL(assign) {
59 mstring name;
60 swrite sw(name);
61 env.eval(sw,L,0);
62 env.sloc(name,R);
63}
64
65X2_IMPL(incr) {
66 mstring name;
67 swrite sw(name);
68 env.eval(sw,L,0);
69 env.sloc(name,ftoa(atof(env.gloc(name))+atof(R)));
70}
71
72X2_IMPL(decr) {
73 mstring name;
74 swrite sw(name);
75 env.eval(sw,L,0);
76 env.sloc(name,ftoa(atof(env.gloc(name))-atof(R)));
77}
78
79//////////////////////////////////////////////////////
80
81X2_IMPL(new_rec) {
82 if(*L=='@') env.gloc_adb(L.popf(),R);
83 else {
84 rpile list; env.gloc_list(list,R);
85 int n=*R=='@'?R.size()-1:R.size();
86 for(int i=0;i<list.size();i++) env.aloc(L+list[i].right(n),env.gloc(list[i]));
87 }
88}
89
90X2_IMPL(copy_rec) {
91 rpile list; env.gloc_list(list,L);
92 int n=*L=='@'?L.size()-1:L.size();
93 for(int i=0;i<list.size();i++) env.sloc(R+list[i].right(n),env.gloc(list[i]));
94}
95
96//////////////////////////////////////////////////////
97
98void envAddOps(opmap& M,tokmap& T)
99{
100 opAddHEXP(M);
101 X1_ADDN(40,0,1,exist,?,
102 "True if a exist\n"
103 "Syntax: ? (varname)\n"
104 "Returns: (int)\n"
105 );
106 X2_ADDN(4,1,2,new,:=,
107 "New assignment\n"
108 "Syntax: (varname) := (expr)\n"
109 "Returns: nothing\n"
110 );
111 X2_ADDN(4,1,2,assign,=,
112 "Assignment to existing variable\n"
113 "Syntax: (varname) = (expr)\n"
114 "Returns: nothing\n"
115 );
116 X2_ADDN(4,1,2,incr,+=,
117 "Increment operator\n"
118 "Syntax: (varname) += (real)\n"
119 "Returns: nothing\n"
120 );
121 X2_ADDN(4,1,2,decr,-=,
122 "Decrement operator\n"
123 "Syntax: (varname) -= (real)\n"
124 "Returns: nothing\n"
125 );
126
127 X2_ADDN(4,1,1,new_rec,<-,
128 "New local record\n"
129 "Syntax: (partial name) <- (partial name)\n"
130 "Returns: nothing\n"
131 "\n"
132 "If the partial name @ is given as the left argument,\n"
133 "a new record is created or silently updated, depending\n"
134 "on whether it is unique or not according to the default order.\n"
135 "The index table must however exist in the right argument.\n"
136 "\n"
137 "The default order may only be set at creation or when saving\n"
138 "a database to disk.\n"
139 );
140 X2_ADDN(4,1,1,copy_rec,->,
141 "Copy local record\n"
142 "Syntax: (partial name) -> (partial name)\n"
143 "Returns: nothing\n"
144 "\n"
145 "The partial name @ for data base records works in both arguments.\n"
146 "\n"
147 "Generates an error if any of the expanded names of the right\n"
148 "partial argument does not exist.\n"
149 );
150}
diff --git a/src/lang/parse.cc b/src/lang/parse.cc
new file mode 100644
index 0000000..7e24a11
--- /dev/null
+++ b/src/lang/parse.cc
@@ -0,0 +1,453 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22static const charset escaped("%$[]{};");
23static const charset prename("\"'`^~*,_=!\\");
24static const charset spec("+-*/%<=>^_!~&|,?:;");
25static const charset spec_latex("+-*/<=>^_;");
26static const charset delim("\"{}()\\");
27static const charset delim_latex("{}()[]\\");
28static const charset specws=spec|delim|cset_ws;
29static const charset specws_latex=spec_latex|delim_latex|cset_ws;
30static const charset tokname=cset_alphareal;
31static const charset pretok=tokname|prename;
32
33const mstring begin_tag="begin",end_left="\\end{",end_right="}";
34
35int is_tokname(const sref& s) {
36 return s.back()!='.'&&pretok.test(s.front())&&s.right(1).find_not_of(tokname)<0;
37}
38
39int is_arglist(const sref& s)
40{
41 const char* p=s.begin(); int opt=0;
42 if(*p=='?') { ++p; opt=1; }
43 while(*p=='x') ++p;
44 while(*p=='r') ++p;
45 if(!opt&&*p=='?') ++p;
46 if(*p=='*') ++p;
47 return !*p;
48}
49
50///////////////////////////////////////////////////////////
51
52static sref getlocal(const sref& in) {
53 int w=0,i=0; for(;i<in.size();i++) {
54 if(in[i]=='[') w++;
55 else if(in[i]==']') w--;
56 else if(!w&&specws.test(in[i])) break;
57 }
58 return in.left(i);
59}
60
61static sref getname(const sref& in) {
62 int i=0;
63 if(pretok.test(*in)) {
64 int w=0;
65 for(i=1;i<in.size();i++) {
66 if(in[i]=='[') w++;
67 else if(in[i]==']') w--;
68 else if(!w&&!tokname.test(in[i])) break;
69 }
70 }
71 if(i>0&&in[i-1]=='.') return in.left(i-1);
72 else return in.left(i);
73}
74
75static int skip_quotes(const sref& in) throw(merror_t) {
76 int s=in.skip(cset_quotes);
77 if(s<0) THROW("parse: unmatched '\"'");
78 return s;
79}
80
81static int skip_braces(const sref& in) throw(merror_t) {
82 int s=in.skip(cset_braces);
83 if(s<0) THROW("parse: unmatched '{'");
84 return s;
85}
86
87static int skip_para(const sref& in) throw(merror_t) {
88 int s=in.skip(cset_para);
89 if(s<0) THROW("parse: unmatched '('");
90 return s;
91}
92
93static int skip_indices(const sref& in) throw(merror_t) {
94 int s=in.skip(cset_indices);
95 if(s<0) THROW("parse: unmatched '['");
96 return s;
97}
98
99static int skip_dollars(const sref& in) throw(merror_t) {
100 int s=in.skip(cset_dollars);
101 //if(s<0) THROW("parse: unmatched '$'");
102 return s;
103}
104
105///////////////////////////////////////////////////////////
106
107static int count_args(const sref& in) throw(merror_t)
108{
109 sref e=in.right_first_not_of(cset_ws);
110 int s,n=0; while((s=skip_braces(e))>0||(s=skip_para(e))>0) {
111 e=e.adv(s).right_first_not_of(cset_ws); n++;
112 }
113 return n;
114}
115
116static int past_args(const sref& in) throw(merror_t)
117{
118 sref p=in,e=in.right_first_not_of(cset_ws);
119 int s; while((s=skip_braces(e))>0||(s=skip_para(e))>0) {
120 e=(p=e.adv(s)).right_first_not_of(cset_ws);
121 }
122 return p-in;
123}
124
125static int parse_args(Env& env,runnable_t* ftok,const sref& in,int inbegend) throw(merror_t)
126{
127 env.clear_args();
128 sref option,p=in,e=in.right_first_not_of(cset_ws);
129 int s,narg=0,carg=count_args(e);
130 while((s=e.skip(cset_braces))>0||(s==0&&(s=e.skip(cset_para))>0)) {
131 if(ftok->arg[narg]=='?'&&carg<ftok->arg.size()) narg++;
132 switch(ftok->arg[narg]){
133 case 'x': env.xpush(e.left(s)); break;
134 case 'r': case '*': env.rpush(e.left(s)); break;
135 case '?': option=e.left(s); break;
136 case 0: THROW("htc: too many args in "<<ftok->name);
137 default: THROW("htc: bad argument descriptor in "<<ftok->name);
138 }
139 e=(p=e.adv(s)).right_first_not_of(cset_ws);
140 if(ftok->arg[narg]!='*') narg++;
141 }
142 if(s<0) THROW("htc: unmatched parenthesis in function "<<ftok->name);
143 if(inbegend) {
144 mstring tag=end_left+ftok->name+end_right;
145 s=p.find(tag); if(s<0) THROW("htc: unmatched begin/end in function "<<ftok->name);
146 if(ftok->arg[narg]=='?'&&carg<ftok->arg.size()) narg++;
147 switch(ftok->arg[narg]){
148 case 'x': env.xpush(p.left(s)); break;
149 case 'r': case '*': env.rpush(p.left(s)); break;
150 case '?': option=p.left(s); break;
151 case 0: THROW("htc: too many args in begin/end "<<ftok->name);
152 default: THROW("htc: bad argument descriptor in "<<ftok->name);
153 }
154 p=p.adv(s+tag.size());
155 }
156 if(ftok->arg.find('?')>=0&&env.args<ftok->arg.size()) env.rpush(option);
157 return p-in;
158}
159
160int Env::check_arg(const runnable_t& ftok) const
161{
162 static const charset tag("xr?");
163 const char* p=ftok.arg.begin(); int x=0,r=0,o=0;
164 while(tag.test(*p)) {
165 switch(*p++) {
166 case 'x': x++; break;
167 case 'r': r++; break;
168 case '?': r++; o++; break;
169 }
170 }
171 if(*p=='*') { o++; ++p; }
172 if(*p||x!=xsize()||o>1||o==1&&rsize()<r||o==0&&r!=rsize()) return 0;
173 return 1;
174}
175
176///////////////////////////////////////////////////////////
177
178void Env::expr(mstream& out,const sref& in) throw(merror_t)
179{
180 expr_t x(in);
181 x.expand(*this);
182 x.eval(out,*this,OP_ALL);
183}
184
185void Env::xpush(const sref& in) throw(merror_t)
186{
187 expr_t* x=new expr_t(in(1,-3));
188 xarg.push_back(x); args++;
189 if(*in=='(') x->expand(*this); else x->status=OP_PARSE;
190 swrite sw(x->result);
191 eval(sw,x,0);
192}
193
194void Env::rpush(const sref& in) throw(merror_t)
195{
196 expr_t* x=new expr_t(in(1,-3));
197 rarg.push_back(x); args++;
198 if(*in=='(') x->expand(*this); else x->status=OP_PARSE;
199}
200
201///////////////////////////////////////////////////////////
202
203static int indent(sref& p) {
204 if(cset_newl.test(p.front())) { p=p.right_first_not_of(cset_ws); return 1; }
205 else return 0;
206}
207
208static int backindent(sref& p) {
209 if(cset_newl.test(p.leftand_last_not_of(cset_spaces).back())) {
210 p=p.leftand_last_not_of(cset_ws); return 1;
211 }
212 else return 0;
213}
214
215static int pastsemi(sref& p) {
216 int s=p.find_not_of(cset_spaces);
217 if(s>=0&&p[s]==';') return indent(p=p.adv(s+1)); else return 0;
218}
219
220static int past_func(const sref& in) throw(merror_t)
221{
222 sref e=getname(in.popf()),p=in.adv(e);
223 return p.adv(past_args(p))-in;
224}
225
226static int parse_func(mstream& out,Env& env,const sref& in,int& run) throw(merror_t)
227{
228 run=0; sref e=getname(in),p=in.adv(e);
229 mstring name;
230 swrite sw(name);
231 env.eval(sw,e,0);
232 if(env.is_arg(name)) {
233 //if(count_args(p)) THROW("htc: expected no argument after "<<name);
234 if(env.up) env.up->parg(out,atoi(name)-1);
235 return p-in;
236 }
237 int inbegend=0;
238 if(name==begin_tag) {
239 sref next=p.right_first_not_of(cset_ws);
240 int s=skip_braces(next);
241 if(s>0) { name=next(1,s-2); p=next.adv(s); inbegend=1; }
242 }
243 tok_t* tok=env.toks->get(name);
244 if(!tok) { if(!(tok=env.loc.get(name))||!tok->is_func()) tok=0; }
245 if(!tok) return 0;
246 if(!tok->is_runnable()) {
247 //if(count_args(p)) THROW("htc: expected no argument after "<<name);
248 if(env.is_clear(tok)) out<<tok->body;
249 return p-in;
250 }
251 runnable_t* ftok=(runnable_t*)tok;
252 if(env.is_clear(ftok)) {
253 p=p.adv(parse_args(env,ftok,p,inbegend));
254 run=1; env.eval(out,ftok,1);
255 }
256 else p=p.adv(past_args(p));
257 return p-in;
258}
259
260void Env::parse(mstream& out,const sref& in) throw(merror_t)
261{
262 static const charset sensors=escaped|cset_newl|'\\';
263 epilog.clear();
264 int s,run;
265 sref p=in;
266 indent(p);
267 backindent(p);
268 sref e=p;
269 while(*p) {
270 switch(*p) {
271 case ';':
272 case '}':
273 case ']':
274 out.put(*p);
275 p=p.popf();
276 break;
277 case '%':
278 if(p-e>0) { out.put(*p); p=p.popf(); }
279 else e=p=p.past_nl().right_first_not_of(cset_ws);
280 break;
281 case '\r':
282 p=p.popf();
283 break;
284 case '\n':
285 out.put(*p); p=p.popf();
286 if(cset_newl.test(*p.right_first_not_of(cset_spaces))) out<<para;
287 e=p=p.right_first_not_of(cset_ws);
288 break;
289 case '{':
290 if(mod&tok_t::PUBLIC){
291 if((s=skip_braces(p))>0) {
292 eval(out,p(1,s-2),0);
293 if(pastsemi(p=p.adv(s))) e=p;
294 }
295 }
296 else { out.put(*p); p=p.popf(); }
297 break;
298 case '[':
299 if(mod&tok_t::PUBLIC){
300 if((s=skip_indices(p))>0) {
301 expr(out,p(1,s-2));
302 if(pastsemi(p=p.adv(s))) e=p;
303 }
304 }
305 else { out.put(*p); p=p.popf(); }
306 break;
307 case '$':
308 if(mod&tok_t::PUBLIC){
309 if((s=skip_dollars(p))>0) {
310 latex_env(*this).expr(out,p(1,s-2));
311 if(pastsemi(p=p.adv(s))) e=p;
312 }
313 }
314 else { out.put(*p); p=p.popf(); }
315 break;
316 case '\\':
317 p=p.popf();
318 if(p.empty()) out.put('\\');
319 else if(escaped.test(*p)) { out.put(*p); p=p.popf(); }
320 else {
321 if((s=parse_func(out,*this,p,run))>0) { if(pastsemi(p=p.adv(s))) e=p; }
322 else out.put('\\');
323 }
324 break;
325 default:
326 if((s=p.find_of(sensors))>=0) { out<<p.left(s); p=p.adv(s); }
327 else { out<<p; p.clear(); }
328 break;
329 }
330 }
331 out<<epilog;
332}
333
334void Env::parse(mstream& out,expr_t* x) throw(merror_t)
335{
336 if(x->status&OP_PARSE) parse(out,x->expr);
337 else x->eval(out,*this,OP_ALL);
338}
339
340///////////////////////////////////////////////////////////
341
342void Env::eval(mstream& out,const sref& in,int child) throw(merror_t)
343{
344 Env nenv(*this); if(child) nenv.up=this;
345 nenv.parse(out,in);
346}
347
348void Env::eval(mstream& out,expr_t* x,int child) throw(merror_t)
349{
350 Env nenv(*this); if(child) nenv.up=this;
351 nenv.parse(out,x);
352}
353
354void Env::eval(mstream& out,runnable_t* ftok,int child) throw(merror_t)
355{
356 if(child&&!check_arg(*ftok)) THROW("htc: bad number of args; expected "<<*ftok);
357 if(ftok->is_binary()) ((binary_t*)ftok)->func(out,*this);
358 else if(ftok->is_func()) eval(out,&((func_t*)ftok)->x,child);
359 else THROW("htc: unknown runnable");
360}
361
362//////////////////////////////////////////////////////
363
364int Env::split(sref& first,sref& rest) throw(merror_t)
365{
366 int s;
367 rest=rest.right_first_not_of(cset_ws);
368 if(*rest=='\\') {
369 first=rest.left(past_func(rest));
370 rest=rest.adv(first);
371 }
372 else if(spec.test(*rest)) {
373 first=rest.left_first_not_of(spec);
374 rest=rest.adv(first);
375 }
376 else if((s=skip_quotes(rest))>0||(s=skip_braces(rest))>0) {
377 first=rest.left(s);
378 rest=rest.adv(first);
379 }
380 else if((s=skip_para(rest))>0) {
381 first=rest(1,s-2);
382 rest=rest.right(s);
383 }
384 else {
385 first=getlocal(rest);
386 rest=rest.adv(first);
387 }
388 return first.nempty();
389}
390
391void Env::term(mstream& out,expr_t* x) throw(merror_t)
392{
393 if(x->expr.empty()) x->status=0;
394 else if(*x->expr=='\"') { out<<x->expr(1,-3); x->status=0; }
395 else if(*x->expr=='{') { eval(out,x->expr(1,-3),0); x->status=0; }
396 else if(x->expr.find_not_of(cset_real)<0) { out<<x->expr; x->status=0; }
397 else if(*x->expr=='\\') {
398 sref p=x->expr.popf();
399 if(p.empty()) { out.put('\\'); x->status=0; }
400 else if(escaped.test(*p)) { out.put(*p); x->status=0; }
401 else {
402 int run;
403 if(parse_func(out,*this,p,run)>0) x->status=run?OP_LOCAL:OP_GLOBAL;
404 else { out.put('\\')<<x->expr; x->status=OP_NINIT; }
405 }
406 }
407 else {
408 mstring name;
409 swrite sw(name);
410 eval(sw,x->expr,0);
411 out<<gloc(name);
412 x->status=OP_LOCAL;
413 }
414}
415
416///////////////////////////////////////////////////////////////////
417
418int latex_env::split(sref& first,sref& rest) throw(merror_t)
419{
420 int s;
421 rest=rest.right_first_not_of(cset_ws);
422 if(*rest=='\\') {
423 first=rest.left(past_func(rest));
424 rest=rest.adv(first);
425 }
426 else if(spec.test(*rest)) {
427 first=rest.left_first_not_of(spec);
428 rest=rest.adv(first);
429 }
430 else if((s=skip_braces(rest))>0||(s=skip_para(rest))>0||(s=skip_indices(rest))>0) {
431 first=rest.left(s);
432 rest=rest.adv(first);
433 }
434 else {
435 first=rest.left_first_of(specws);
436 rest=rest.adv(first);
437 }
438 return first.nempty();
439}
440
441void latex_env::term(mstream& out,expr_t* x) throw(merror_t)
442{
443 if(x->expr.empty()) x->status=0;
444 else if(*x->expr=='\\') { eval(out,x->expr,0); x->status=0; }
445 else if(*x->expr=='{') { eval(out,x->expr(1,-3),0); x->status=0; }
446 else if(*x->expr=='('||*x->expr=='[') {
447 out.put(x->expr.front());
448 expr(out,x->expr(1,-3));
449 out.put(x->expr.back());
450 x->status=0;
451 }
452 else { out<<x->expr; x->status=0; }
453}
diff --git a/src/lang/test.cc b/src/lang/test.cc
new file mode 100644
index 0000000..e59a719
--- /dev/null
+++ b/src/lang/test.cc
@@ -0,0 +1,45 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/env.h>
21
22static fp_stream mout(stdout),merr(stderr);
23
24main(int argc,char* argv[]) try
25{
26 Lang lang;
27 req_env req(lang,lang.toks);
28 Env env(lang.ops,req,XSYSTEM);
29 mstring line;
30 while(!feof(stdin)) {
31 merr<<"lang>";
32 getline(line,stdin);
33 try {
34 env.parse(mout,line);
35 mout<<"\n";
36 }
37 catch(const merror_t& e) {
38 merr<<e.desc<<"\n";
39 }
40 }
41 return 0;
42}
43catch(const merror_t& e) {
44 merr<<"ERROR: ["<<e.desc<<"]\n";
45}
diff --git a/src/lang/token.cc b/src/lang/token.cc
new file mode 100644
index 0000000..5bee9ca
--- /dev/null
+++ b/src/lang/token.cc
@@ -0,0 +1,268 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/token.h>
21#include <algorithm>
22using namespace std;
23
24///////////////////////////////////////////////////////////////////
25
26const unsigned tok_t::CONSTANT=1;
27const unsigned tok_t::RESTRICT=2;
28const unsigned tok_t::NORMAL=4;
29const unsigned tok_t::SYSONLY=8;
30const unsigned tok_t::INIT=16;
31const unsigned tok_t::RUNNABLE=32;
32const unsigned tok_t::FUNCTION=64;
33const unsigned tok_t::BINARY=128;
34const unsigned tok_t::REFERENCE=256;
35const unsigned tok_t::DBREF=512;
36const unsigned tok_t::CRON=1024;
37const unsigned tok_t::PRIVATE=NORMAL|SYSONLY;
38const unsigned tok_t::PUBLIC=RESTRICT|PRIVATE;
39const unsigned tok_t::XMODES=PUBLIC|INIT;
40
41///////////////////////////////////////////////////////////////////
42
43uniheap<sizeof(tok_t)> tok_t::tree;
44void* tok_t::operator new(size_t n) { return tree.push(); }
45void tok_t::operator delete(void* p) { tree.pop(p); }
46
47uniheap<sizeof(reference_t)> reference_t::tree;
48void* reference_t::operator new(size_t n) { return tree.push(); }
49void reference_t::operator delete(void* p) { tree.pop(p); }
50
51uniheap<sizeof(dbref_t)> dbref_t::tree;
52void* dbref_t::operator new(size_t n) { return tree.push(); }
53void dbref_t::operator delete(void* p) { tree.pop(p); }
54
55uniheap<sizeof(runnable_t)> runnable_t::tree;
56void* runnable_t::operator new(size_t n) { return tree.push(); }
57void runnable_t::operator delete(void* p) { tree.pop(p); }
58
59uniheap<sizeof(func_t)> func_t::tree;
60void* func_t::operator new(size_t n) { return tree.push(); }
61void func_t::operator delete(void* p) { tree.pop(p); }
62
63uniheap<sizeof(cron_t)> cron_t::tree;
64void* cron_t::operator new(size_t n) { return tree.push(); }
65void cron_t::operator delete(void* p) { tree.pop(p); }
66
67uniheap<sizeof(binary_t)> binary_t::tree;
68void* binary_t::operator new(size_t n) { return tree.push(); }
69void binary_t::operator delete(void* p) { tree.pop(p); }
70
71///////////////////////////////////////////////////////////////////
72
73mstring uscore2dot(const char* s) {
74 mstring t=s; int p; while((p=t.find('_'))>=0) t[p]='.'; return t;
75}
76
77///////////////////////////////////////////////////////////////////
78
79tok_t::~tok_t() {}
80
81///////////////////////////////////////////////////////////////////
82
83void tokmap::clear()
84{
85 for(iterator p=list.begin();p!=list.end();p++) delete *p;
86 list.clear();
87}
88
89tok_t* tokmap::get_this(const sref& t)
90{
91 pair<iterator,iterator> p=equal_range(list.begin(),list.end(),(val_t)0,comp_t(t));
92 return p.first!=p.second?*p.first:0;
93}
94
95const tok_t* tokmap::get_this(const sref& t) const
96{
97 pair<const_iterator,const_iterator> p=
98 equal_range(list.begin(),list.end(),(val_t)0,comp_t(t));
99 return p.first!=p.second?*p.first:0;
100}
101
102const tok_t* tokmap::get(const sref& t) const
103{
104 const tok_t* p=get_this(t); return p?p:up?up->get(t):0;
105}
106
107tok_t* tokmap::get(const sref& t)
108{
109 tok_t* p=get_this(t); return p?p:up?up->get(t):0;
110}
111
112tok_t* tokmap::set(tok_t* tok,int replace,int force) throw(merror_t)
113{
114 pair<iterator,iterator> p=
115 equal_range(list.begin(),list.end(),(val_t)0,comp_t(tok->name));
116 if(p.first!=p.second) {
117 if(!(*p.first)->is_replaceable(*tok)) {
118 delete tok;
119 THROW("token: Could not set "<<(*p.first)->name<<" - protected");
120 return 0;
121 }
122 else if((*p.first)->is_const()&&!replace) {
123 delete tok;
124 if(force) THROW("token: Could not set "<<(*p.first)->name<<" - constant");
125 return 0;
126 }
127 else { delete *p.first; return *p.first=tok; }
128 }
129 else if(up) return up->set(tok,replace,force);
130 else {
131 mstring name=tok->name;
132 delete tok;
133 if(force) THROW("token: Could not set "<<name<<" - not found");
134 return 0;
135 }
136}
137
138tok_t* tokmap::add(tok_t* tok,int replace,int force) throw(merror_t)
139{
140 tok_t* old=get(tok->name);
141 if(old) {
142 if(!old->is_replaceable(*tok)) {
143 delete tok;
144 THROW("token: Could not add "<<old->name<<" - protected");
145 return 0;
146 }
147 else if(old->is_const()&&!replace) {
148 delete tok;
149 if(force) THROW("token: Could not add "<<old->name<<" - constant");
150 return 0;
151 }
152 }
153 pair<iterator,iterator> p=
154 equal_range(list.begin(),list.end(),(val_t)0,comp_t(tok->name));
155 if(p.first!=p.second) { delete *p.first; return *p.first=tok; }
156 else return *list.insert(p.second,tok);
157}
158
159///////////////////////////////////////////////////////////////////
160
161static void Check(const sref& s) throw(merror_t)
162{
163 if(!is_tokname(s)) THROW("token: bad name ("<<s<<")");
164}
165
166static void CheckArg(const sref& s) throw(merror_t)
167{
168 if(!is_arglist(s)) THROW("ftok: bad argspec ("<<s<<")");
169}
170
171///////////////////////////////////////////////////////////////////
172
173tok_t* Cond(tokmap& map,const sref& s,const sref& b,unsigned m) throw(merror_t)
174{
175 Check(s);
176 return map.add(new tok_t(s,b,m),0,0);
177}
178
179tok_t* Global(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl) throw(merror_t)
180{
181 Check(s);
182 return map.add(new tok_t(s,b,m),rpl,1);
183}
184
185tok_t* Const(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl) throw(merror_t)
186{
187 Check(s);
188 return map.add(new tok_t(s,b,m|tok_t::CONSTANT),rpl,1);
189}
190
191func_t* Func(tokmap& map,const sref& s,const sref& b,
192 unsigned m,const sref& a,int rpl) throw(merror_t)
193{
194 Check(s);
195 CheckArg(a);
196 return (func_t*)map.add(new func_t(s,b,m,a),rpl,1);
197}
198
199cron_t* Cron(tokmap& map,const sref& s,const sref& b,
200 unsigned m,int i,int rpl) throw(merror_t)
201{
202 Check(s);
203 return (cron_t*)map.add(new cron_t(s,b,m,i),rpl,1);
204}
205
206binary_t* Binary(tokmap& map,const sref& s,const sref& b,
207 unsigned m,const sref& a,s_func_t f,int rpl) throw(merror_t)
208{
209 Check(s);
210 CheckArg(a);
211 return (binary_t*)map.add(new binary_t(s,b,m,a,f),rpl,1);
212}
213
214reference_t* Reference(tokmap& map,const sref& s,
215 const sref& b,unsigned m,int rpl) throw(merror_t)
216{
217 Check(s);
218 return (reference_t*)map.add(new reference_t(s,b,m),rpl,1);
219}
220
221dbref_t* DBRef(tokmap& map,const sref& s,
222 const sref& b,unsigned m,int rpl) throw(merror_t)
223{
224 Check(s);
225 return (dbref_t*)map.add(new dbref_t(s,b,m),rpl,1);
226}
227
228void ClearToken(tokmap& map,const sref& s) throw(merror_t)
229{
230 if(s.nempty()) {
231 tokmap::iterator p=map.begin();
232 while(p<map.end()) {
233 if((*p)->name.left(s.size())==s) p=map.erase(p); else p++;
234 }
235 }
236}
237
238///////////////////////////////////////////////////////////////
239
240mstream& operator<<(mstream& out,const runnable_t& ftok)
241{
242 out<<"\\"<<ftok.name;
243 for(const char* p=ftok.arg.begin();p!=ftok.arg.end();p++) out.put('{').put(*p).put('}');
244 return out;
245}
246
247mstring Mode(const tok_t& tok)
248{
249 mstring m;
250 for(int i=11;i>=0;i--) { if(tok.mod&(1<<i)) m+='1'; else m+='0'; }
251 return m;
252}
253
254mstring Desc(const tok_t& tok)
255{
256 mstring m;
257 sref first,rest=tok.body;
258 while(Splitln(first,rest)) {
259 first=first.right_first_not_of(cset_ws);
260 if(*first=='%') {
261 first=first.popf().right_first_not_of(cset_ws);
262 m+=first;
263 m+='\n';
264 }
265 }
266 return m;
267}
268
diff --git a/src/lang/token.h b/src/lang/token.h
new file mode 100644
index 0000000..bf32820
--- /dev/null
+++ b/src/lang/token.h
@@ -0,0 +1,230 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef TOKENH
21#define TOKENH
22
23#include <ops/express.h>
24#include <hdb/db.h>
25
26#define TOK_ARGS (mstream& out,Env& env)
27#define TOK_IMPL(func) static void impl_##func TOK_ARGS throw(merror_t)
28#define TOK_ADD(func,a,mod,help) \
29T.add(new binary_t(uscore2dot(#func),sref(help),mod,sref(a),impl_##func),0,1)
30
31mstring uscore2dot(const char* s);
32
33class Env;
34typedef void (*s_func_t)TOK_ARGS;
35
36class tok_t {
37public:
38 static const unsigned CONSTANT,RESTRICT,NORMAL,SYSONLY,INIT;
39 static const unsigned RUNNABLE,FUNCTION,BINARY;
40 static const unsigned REFERENCE,DBREF,CRON;
41 static const unsigned PRIVATE,PUBLIC,XMODES;
42
43 static inline unsigned tight(unsigned xmod) {
44 // INIT is ignored here simply because no mode can
45 // read variables in INIT mode... defaults to public.
46 return (xmod&SYSONLY)?SYSONLY:(xmod&NORMAL)?PRIVATE:PUBLIC;
47 }
48
49 mstring name,body;
50 unsigned mod;
51
52 int is_clear(int xmod) const { return (mod&xmod)!=0; }
53 int is_replaceable(const tok_t& t) const { return (mod&t.mod)==t.mod; }
54
55 int is_const() const { return (mod&CONSTANT)!=0; }
56 int is_runnable() const { return (mod&RUNNABLE)!=0; }
57 int is_func() const { return (mod&FUNCTION)!=0; }
58 int is_cron() const { return (mod&CRON)!=0; }
59 int is_binary() const { return (mod&BINARY)!=0; }
60 int is_reference() const { return (mod&REFERENCE)!=0; }
61 int is_dbref() const { return (mod&DBREF)!=0; }
62
63 tok_t(const sref& s,const sref& b,unsigned m) : name(s),body(b),mod(m) {}
64 virtual ~tok_t();
65
66 static void* operator new(size_t n);
67 static void operator delete(void* p);
68private:
69 static uniheap<32> tree;
70};
71
72///////////////////////////////////////////////////////////////////
73
74class reference_t : public tok_t {
75public:
76 mstring data;
77 reference_t(const sref& s,const sref& b,unsigned m):
78 tok_t(s,b,m|REFERENCE|CONSTANT) {}
79
80 static void* operator new(size_t n);
81 static void operator delete(void* p);
82private:
83 static uniheap<44> tree;
84};
85
86///////////////////////////////////////////////////////////////////
87
88class dbref_t : public tok_t {
89public:
90 dbmap db;
91 dbref_t(const sref& s,const sref& b,unsigned m):
92 tok_t(s,b,m|DBREF|CONSTANT) {}
93
94 static void* operator new(size_t n);
95 static void operator delete(void* p);
96private:
97 static uniheap<96> tree;
98};
99
100///////////////////////////////////////////////////////////////////
101
102class runnable_t : public tok_t {
103public:
104 mstring arg;
105 runnable_t(const sref& s,const sref& b,unsigned m,const sref& a):
106 tok_t(s,b,m|RUNNABLE|CONSTANT),arg(a) {}
107
108 static void* operator new(size_t n);
109 static void operator delete(void* p);
110private:
111 static uniheap<44> tree;
112};
113
114///////////////////////////////////////////////////////////////////
115
116class func_t : public runnable_t {
117public:
118 expr_t x;
119 func_t(const sref& s,const sref& b,unsigned m,const sref& a):
120 runnable_t(s,b,m|FUNCTION,a) { x=body; }
121
122 static void* operator new(size_t n);
123 static void operator delete(void* p);
124private:
125 static uniheap<80> tree;
126};
127
128///////////////////////////////////////////////////////////////////
129
130class cron_t : public func_t {
131public:
132 int last,interval;
133 cron_t(const sref& s,const sref& b,unsigned m,int i):
134 func_t(s,b,m|CRON,ms_empty),last(0),interval(i) {}
135
136 static void* operator new(size_t n);
137 static void operator delete(void* p);
138private:
139 static uniheap<88> tree;
140};
141
142///////////////////////////////////////////////////////////////////
143
144class binary_t : public runnable_t {
145public:
146 s_func_t func;
147 binary_t(const sref& s,const sref& b,unsigned m,const sref& a,s_func_t f):
148 runnable_t(s,b,m|BINARY,a),func(f) {}
149
150 static void* operator new(size_t n);
151 static void operator delete(void* p);
152private:
153 static uniheap<48> tree;
154};
155
156///////////////////////////////////////////////////////////////////
157
158mstream& operator<<(mstream&,const runnable_t& ftok);
159mstring Mode(const tok_t& tok);
160mstring Desc(const tok_t& tok);
161
162///////////////////////////////////////////////////////////////////
163
164struct tokmap {
165 typedef tok_t* val_t;
166 typedef mrvec<val_t> map_t;
167 typedef map_t::iterator iterator;
168 typedef map_t::const_iterator const_iterator;
169
170 struct comp_t {
171 sref key;
172 comp_t(const sref& skey) : key(skey) {}
173 bool operator()(val_t a,val_t b) const {
174 return (a?((const sref&)a->name):key)<(b?((const sref&)b->name):key);
175 }
176 };
177
178 tokmap* up;
179 map_t list;
180
181 tokmap() : up(0),list() {}
182 tokmap(tokmap& p) : up(&p),list() {}
183 ~tokmap() { clear(); }
184
185 iterator begin() { return list.begin(); }
186 const_iterator begin() const { return list.begin(); }
187
188 iterator end() { return list.end(); }
189 const_iterator end() const { return list.end(); }
190
191 void clear();
192 iterator erase(iterator p) { delete *p; return list.erase(p); }
193
194 tok_t* get_this(const sref& t);
195 const tok_t* get_this(const sref& t) const;
196 const tok_t* get(const sref& t) const;
197 tok_t* get(const sref& t);
198
199 tok_t* set(tok_t* tok,int replace,int force) throw(merror_t);
200 tok_t* add(tok_t* tok,int replace,int force) throw(merror_t);
201};
202
203///////////////////////////////////////////////////////////////////
204
205int is_tokname(const sref& s);
206int is_arglist(const sref& s);
207
208tok_t* Cond(tokmap& map,const sref& s,const sref& b,unsigned m) throw(merror_t);
209tok_t* Global(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl=0) throw(merror_t);
210tok_t* Const(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl=0) throw(merror_t);
211func_t* Func(tokmap& map,const sref& s,const sref& b,
212 unsigned m,const sref& a,int rpl=0) throw(merror_t);
213cron_t* Cron(tokmap& map,const sref& s,const sref& b,
214 unsigned m,int i,int rpl=0) throw(merror_t);
215binary_t* Binary(tokmap& map,const sref& s,const sref& b,
216 unsigned m,const sref& a,s_func_t f,int rpl=0) throw(merror_t);
217reference_t* Reference(tokmap& map,const sref& s,const sref& b,
218 unsigned m,int rpl=0) throw(merror_t);
219dbref_t* DBRef(tokmap& map,const sref& s,
220 const sref& b,unsigned m,int rpl=0) throw(merror_t);
221void ClearToken(tokmap& map,const sref& s) throw(merror_t);
222
223///////////////////////////////////////////////////////////////////
224
225const int XPUBLIC=tok_t::RESTRICT;
226const int XPRIVATE=XPUBLIC|tok_t::NORMAL;
227const int XSYSTEM=XPRIVATE|tok_t::SYSONLY;
228const int XINIT=tok_t::INIT;
229
230#endif
diff --git a/src/mail/inbox.cc b/src/mail/inbox.cc
new file mode 100644
index 0000000..b605cd3
--- /dev/null
+++ b/src/mail/inbox.cc
@@ -0,0 +1,36 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mail/res.h>
21#include <mt/lock.h>
22#include <unistd.h>
23
24main(int argc,char* argv[])
25{
26 if(argc<3) return -1;
27 const char* infile=INBOX.c_str(); // argv[1] not used
28 const char* outfile=argv[2];
29 LockFile(infile);
30 Mailbox box;
31 GetMessages(box,infile);
32 int ok=AppendMessages(box,outfile);
33 if(ok) truncate(infile,0);
34 UnlockFile(infile);
35 return !ok;
36}
diff --git a/src/mail/list.cc b/src/mail/list.cc
new file mode 100644
index 0000000..f50c41b
--- /dev/null
+++ b/src/mail/list.cc
@@ -0,0 +1,52 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mail/res.h>
21#include <mime/enc.h>
22
23static fp_stream mout(stdout),merr(stderr);
24const mstring multipart="multipart/";
25
26main(int argc,char* argv[]) try
27{
28 if(argc<2) {
29 merr<<"Usage: "<<argv[0]<<" <inbox> [index]\n";
30 return -1;
31 }
32 const char* infile=argv[1];
33 Mailbox box;
34 GetMessages(box,infile);
35 if(argc>2) {
36 int m=atoi(argv[2])-1;
37 if(m>=0&&m<box.size()) mout<<box[m]<<"\n";
38 }
39 else {
40 merr<<"Read "<<box.size()<<" messages.\n";
41 for(int i=0;i<box.size();i++) {
42 Message msg(box[i]);
43 int multi=msg.cont_type.find(multipart)>=0;
44 mout<<"["<<(i+1)<<"]["<<multi<<"]["<<msg.subject<<"]["<<msg.from<<"]\n";
45 }
46 }
47 return 0;
48}
49catch(const merror_t& e)
50{
51 fprintf(stderr,"main: %d: %s\n",e.num,e.desc.c_str());
52}
diff --git a/src/mail/move.cc b/src/mail/move.cc
new file mode 100644
index 0000000..bbcce0d
--- /dev/null
+++ b/src/mail/move.cc
@@ -0,0 +1,60 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mail/res.h>
21#include <mt/lock.h>
22
23static fp_stream mout(stdout),merr(stderr);
24
25main(int argc,char* argv[])
26{
27 if(argc<3) {
28 merr<<"Usage: "<<argv[0]<<" <frombox> <tobox> [indices]\n";
29 return -1;
30 }
31 const char* infile=argv[1];
32 const char* outfile=argv[2];
33 Mailbox box,keep;
34 LockFile(infile);
35 LockFile(outfile);
36 FILE* outbox=fopen(outfile,"a+");
37 if(outbox) {
38 GetMessages(box,infile);
39 for(int i=0;i<box.size();i++) {
40 int move=0;
41 if(argc>3) {
42 for(int j=3;j<argc;j++) if(atoi(argv[j])-1==i) { move=1; break; }
43 }
44 else {
45 move=1;
46 }
47 if(move) AppendMessage(outbox,box[i]);
48 else keep.push_back(box[i]);
49 }
50 if(fclose(outbox)) {
51 merr<<"Write error: messages kept (but possibly duplicates).\n";
52 }
53 else {
54 PutMessages(keep,infile);
55 }
56 }
57 UnlockFile(outfile);
58 UnlockFile(infile);
59 return 0;
60}
diff --git a/src/mail/res.h b/src/mail/res.h
new file mode 100644
index 0000000..5c54c31
--- /dev/null
+++ b/src/mail/res.h
@@ -0,0 +1,30 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MAILRESH
21#define MAILRESH
22
23#include <mime/mailbox.h>
24#include <mt/config.h>
25
26const mstring INBOX=htchome()+sref("/mail/INBOX");
27const mstring TODO=htchome()+sref("/mail/TODO");
28const mstring DONE=htchome()+sref("/mail/DONE");
29
30#endif
diff --git a/src/makefile b/src/makefile
new file mode 100644
index 0000000..09670b2
--- /dev/null
+++ b/src/makefile
@@ -0,0 +1,177 @@
1 #########################################################################
2 #
3 # HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #
19
20LIBRARY = libhtc.a
21INSTALL = ../bin
22
23############################################################################
24
25MODULE += mt
26mt_c = test
27mt_o = cfind crfind strip \
28 sfind srfind sfindtab srfindtab scomptab sconvert \
29 find_of rfind_of find_not_of rfind_not_of skip_parentesis \
30 stringref mstream mread mstring mset msmap \
31 random dates lock lookup issue config
32
33
34MODULE += mime
35mime_c = test
36mime_o = mime def mailbox base64 qp pack
37
38
39MODULE += mail
40mail_c = inbox move list
41
42
43MODULE += http
44http_c = test
45http_o = mime req resp
46
47
48MODULE += ops
49ops_c = test
50ops_o = operator express basic comp string latex
51
52
53MODULE += hdb
54hdb_c = test hdbtest hdbcvt hdbfix
55hdb_o = filemap sortable db comp cvt
56
57
58MODULE += hed
59hed_c = test hed
60hed_o = input edit tables
61hed_x = hed
62
63
64MODULE += lang
65lang_c = test
66lang_o = token env parse ops basic func latex help flow db lang
67
68
69MODULE += sh
70sh_c = htc
71sh_o = file convert dates user tree sys net main
72sh_x = htc
73
74MODULE += serv
75serv_c = htcs
76serv_o = direct request const auth form tempmap main
77serv_x = htcs
78
79MODULE += net
80net_c = test htcd redirect route80
81net_o = isocket server thrserv
82net_x = htcd redirect
83
84MODULE += labat
85labat_c = atomlab
86labat_f = labat
87labat_o = resten deriv grad grabgr laplac laplac2 ggaexc \
88 exchen ldaec gcor ggaec ggauxc exchpt ldauc \
89 ggauc spline splint
90labat_x = atomlab labat
91
92############################################################################
93
94CTARGET = $(foreach mod,$(MODULE),\
95 $(addprefix $(mod)/,$($(mod)_c)))
96
97FTARGET = $(foreach mod,$(MODULE),\
98 $(addprefix $(mod)/,$($(mod)_f)))
99
100LTARGET = $(foreach mod,$(MODULE),\
101 $(addprefix $(mod)/,$($(mod)_o)))
102
103XTARGET = $(foreach mod,$(MODULE),\
104 $(addprefix $(mod)/,$($(mod)_x)))
105
106XLIST = $(foreach mod,$(MODULE),$($(mod)_x))
107
108CTARG = $(addprefix tmp/bin/,$(CTARGET))
109FTARG = $(addprefix tmp/bin/,$(FTARGET))
110XTARG = $(addprefix tmp/bin/,$(XTARGET))
111COBJ = $(addprefix tmp/obj/c/,$(addsuffix .o,$(CTARGET)))
112FOBJ = $(addprefix tmp/obj/f/,$(addsuffix .o,$(FTARGET)))
113LOBJ = $(addprefix tmp/obj/l/,$(addsuffix .o,$(LTARGET)))
114TLIB = $(addprefix tmp/obj/,$(LIBRARY))
115
116############################################################################
117
118INCLUDE = -I.
119COPT = -O3 -pthread
120FOPT = -O5
121CLIBS = -lncurses
122FLIBS =
123
124.PHONY: all man html clean mkobj install
125.PRECIOUS: tmp/obj/c/%.o tmp/obj/f/%.o tmp/obj/l/%.o
126
127############################################################################
128
129all: $(LOBJ) $(TLIB) $(FOBJ) $(COBJ) $(FTARG) $(CTARG)
130
131tmp/bin/%: tmp/obj/c/%.o $(TLIB)
132 @mkdir -p $(@D)
133 g++ $(COPT) $< $(TLIB) $(CLIBS) -o $@
134
135tmp/bin/%: tmp/obj/f/%.o $(TLIB)
136 @mkdir -p $(@D)
137 f77 $(FOPT) $< $(TLIB) $(FLIBS) -o $@
138
139tmp/obj/c/%.o: %.cc
140 @mkdir -p $(@D)
141 gcc $(INCLUDE) $(COPT) -c $< -o $@
142
143tmp/obj/f/%.o: %.f
144 @mkdir -p $(@D)
145 f77 $(FOPT) -c $< -o $@
146
147$(TLIB): $(LOBJ)
148 @rm -f $(TLIB)
149 ar qc $(TLIB) $(LOBJ)
150
151tmp/obj/l/%.o: %.cc
152 @mkdir -p $(@D)
153 gcc $(INCLUDE) $(COPT) -c $< -o $@
154
155tmp/obj/l/%.o: %.f
156 @mkdir -p $(@D)
157 f77 $(FOPT) -c $< -o $@
158
159man:
160 @rm -rf tmp/man
161 doxygen etc/doxman
162
163html:
164 @rm -rf tmp/html
165 doxygen etc/doxhtml
166
167install: $(XTARG)
168 @mkdir -p $(INSTALL)
169 cp -rfp $(XTARG) $(INSTALL)
170
171clean:
172 rm -rf tmp
173
174distclean:
175 rm -rf tmp; cd $(INSTALL); rm -rf $(XLIST)
176
177############################################################################
diff --git a/src/mime/base64.cc b/src/mime/base64.cc
new file mode 100644
index 0000000..842bbd3
--- /dev/null
+++ b/src/mime/base64.cc
@@ -0,0 +1,132 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/enc.h>
21
22static unsigned char char2six[256]={
23 65,65,65,65,65,65,65,65,
24 65,65,65,65,65,65,65,65,
25 65,65,65,65,65,65,65,65,
26 65,65,65,65,65,65,65,65,
27 65,65,65,65,65,65,65,65,
28 65,65,65,62,65,65,65,63,
29 52,53,54,55,56,57,58,59,
30 60,61,65,65,65,64,65,65,
31 65, 0, 1, 2, 3, 4, 5, 6,
32 7, 8, 9,10,11,12,13,14,
33 15,16,17,18,19,20,21,22,
34 23,24,25,65,65,65,65,65,
35 65,26,27,28,29,30,31,32,
36 33,34,35,36,37,38,39,40,
37 41,42,43,44,45,46,47,48,
38 49,50,51,65,65,65,65,65,
39 65,65,65,65,65,65,65,65,
40 65,65,65,65,65,65,65,65,
41 65,65,65,65,65,65,65,65,
42 65,65,65,65,65,65,65,65,
43 65,65,65,65,65,65,65,65,
44 65,65,65,65,65,65,65,65,
45 65,65,65,65,65,65,65,65,
46 65,65,65,65,65,65,65,65,
47 65,65,65,65,65,65,65,65,
48 65,65,65,65,65,65,65,65,
49 65,65,65,65,65,65,65,65,
50 65,65,65,65,65,65,65,65,
51 65,65,65,65,65,65,65,65,
52 65,65,65,65,65,65,65,65,
53 65,65,65,65,65,65,65,65,
54 65,65,65,65,65,65,65,65
55};
56static unsigned char six2char[64]={
57 'A','B','C','D','E','F','G','H',
58 'I','J','K','L','M','N','O','P',
59 'Q','R','S','T','U','V','W','X',
60 'Y','Z','a','b','c','d','e','f',
61 'g','h','i','j','k','l','m','n',
62 'o','p','q','r','s','t','u','v',
63 'w','x','y','z','0','1','2','3',
64 '4','5','6','7','8','9','+','/'
65};
66inline void tri2quad(mstream& out,unsigned code,int m=4)
67{
68 char buf[4];
69 buf[3]=six2char[code&63U]; code>>=6;
70 buf[2]=six2char[code&63U]; code>>=6;
71 buf[1]=six2char[code&63U]; code>>=6;
72 buf[0]=six2char[code&63U];
73 out.write(buf,m);
74}
75inline void quad2tri(mstream& out,unsigned code,int m=3)
76{
77 char buf[3];
78 buf[2]=code&255U; code>>=8;
79 buf[1]=code&255U; code>>=8;
80 buf[0]=code&255U;
81 out.write(buf,m);
82}
83
84void encode64(mstream& out,const sref& in)
85{
86 unsigned m=0,code=0,wrap=0;
87 for(const char* p=in.begin();p!=in.end();p++) {
88 code<<=8;
89 code|=(unsigned char)*p;
90 if(++m==3) {
91 tri2quad(out,code);
92 m=0;
93 if(++wrap==15) { out<<CRLF; wrap=0; }
94 }
95 }
96 if(m==1) {
97 code<<=16;
98 tri2quad(out,code,2);
99 out<<"==";
100 if(++wrap==15) { out<<CRLF; wrap=0; }
101 }
102 else if(m==2) {
103 code<<=8;
104 tri2quad(out,code,3);
105 out.put('=');
106 if(++wrap==15) { out<<CRLF; wrap=0; }
107 }
108 if(wrap>0) out<<CRLF;
109}
110
111void decode64(mstream& out,const sref& in)
112{
113 unsigned m=0,code=0,six=0;
114 for(const char* p=in.begin();p!=in.end();p++) {
115 six=char2six[(unsigned char)*p];
116 if(six>=64) continue;
117 code<<=6;
118 code|=six;
119 if(++m==4) {
120 quad2tri(out,code);
121 m=0;
122 }
123 }
124 if(m==2) {
125 code<<=12;
126 quad2tri(out,code,1);
127 }
128 else if(m==3) {
129 code<<=6;
130 quad2tri(out,code,2);
131 }
132}
diff --git a/src/mime/def.cc b/src/mime/def.cc
new file mode 100644
index 0000000..0a692cd
--- /dev/null
+++ b/src/mime/def.cc
@@ -0,0 +1,149 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/mime.h>
21#include <mt/msmap.h>
22
23struct table_t { char ext[16],name[64]; };
24
25static table_t table[]={
26 {"ai","application/postscript"},
27 {"aif","audio/x-aiff"},
28 {"aifc","audio/x-aiff"},
29 {"aiff","audio/x-aiff"},
30 {"au","audio/basic"},
31 {"avi","video/x-msvideo"},
32 {"bcpio","application/x-bcpio"},
33 {"bin","application/octet-stream"},
34 {"cdf","application/x-netcdf"},
35 {"class","application/octet-stream"},
36 {"cpio","application/x-cpio"},
37 {"cpt","application/mac-compactpro"},
38 {"csh","application/x-csh"},
39 {"css","text/css"},
40 {"dcr","application/x-director"},
41 {"dir","application/x-director"},
42 {"dms","application/octet-stream"},
43 {"doc","application/msword"},
44 {"dvi","application/x-dvi"},
45 {"dxr","application/x-director"},
46 {"eps","application/postscript"},
47 {"etx","text/x-setext"},
48 {"exe","application/octet-stream"},
49 {"gif","image/gif"},
50 {"gtar","application/x-gtar"},
51 {"gz","application/x-gzip"},
52 {"hdf","application/x-hdf"},
53 {"hqx","application/mac-binhex40"},
54 {"htc","text/x-htc"},
55 {"hts","text/plain"},
56 {"htx","text/x-htx"},
57 {"htm","text/html"},
58 {"html","text/html"},
59 {"ice","x-conference/x-cooltalk"},
60 {"ief","image/ief"},
61 {"jpe","image/jpeg"},
62 {"jpeg","image/jpeg"},
63 {"jpg","image/jpeg"},
64 {"kar","audio/midi"},
65 {"latex","application/x-latex"},
66 {"lha","application/octet-stream"},
67 {"lzh","application/octet-stream"},
68 {"man","application/x-troff-man"},
69 {"me","application/x-troff-me"},
70 {"mid","audio/midi"},
71 {"midi","audio/midi"},
72 {"mif","application/x-mif"},
73 {"mov","video/quicktime"},
74 {"movie","video/x-sgi-movie"},
75 {"mp2","audio/mpeg"},
76 {"mp3","audio/mpeg"},
77 {"mpe","video/mpeg"},
78 {"mpeg","video/mpeg"},
79 {"mpg","video/mpeg"},
80 {"mpga","audio/mpeg"},
81 {"ms","application/x-troff-ms"},
82 {"nc","application/x-netcdf"},
83 {"oda","application/oda"},
84 {"pbm","image/x-portable-bitmap"},
85 {"pdb","chemical/x-pdb"},
86 {"pdf","application/pdf"},
87 {"pgm","image/x-portable-graymap"},
88 {"png","image/png"},
89 {"pnm","image/x-portable-anymap"},
90 {"ppm","image/x-portable-pixmap"},
91 {"ppt","application/powerpoint"},
92 {"ps","application/postscript"},
93 {"qt","video/quicktime"},
94 {"ra","audio/x-realaudio"},
95 {"ram","audio/x-pn-realaudio"},
96 {"ras","image/x-cmu-raster"},
97 {"rgb","image/x-rgb"},
98 {"roff","application/x-troff"},
99 {"rpm","audio/x-pn-realaudio-plugin"},
100 {"rtf","application/rtf"},
101 {"rtx","text/richtext"},
102 {"sgm","text/x-sgml"},
103 {"sgml","text/x-sgml"},
104 {"sh","application/x-sh"},
105 {"shar","application/x-shar"},
106 {"sit","application/x-stuffit"},
107 {"skd","application/x-koan"},
108 {"skm","application/x-koan"},
109 {"skp","application/x-koan"},
110 {"skt","application/x-koan"},
111 {"snd","audio/basic"},
112 {"src","application/x-wais-source"},
113 {"sv4cpio","application/x-sv4cpio"},
114 {"sv4crc","application/x-sv4crc"},
115 {"t","application/x-troff"},
116 {"tar","application/x-tar"},
117 {"tcl","application/x-tcl"},
118 {"tex","application/x-tex"},
119 {"texi","application/x-texinfo"},
120 {"texinfo","application/x-texinfo"},
121 {"tif","image/tiff"},
122 {"tiff","image/tiff"},
123 {"tr","application/x-troff"},
124 {"tsv","text/tab-separated-values"},
125 {"txt","text/plain"},
126 {"ustar","application/x-ustar"},
127 {"vcd","application/x-cdlink"},
128 {"vrml","x-world/x-vrml"},
129 {"wav","audio/x-wav"},
130 {"wrl","x-world/x-vrml"},
131 {"xbm","image/x-xbitmap"},
132 {"xpm","image/x-xpixmap"},
133 {"xwd","image/x-xwindowdump"},
134 {"xyz","chemical/x-pdb"},
135 {"zip","application/zip"},
136 {"",""}
137};
138
139const sref* file2mime(const sref& file)
140{
141 static rrmap mime;
142 if(mime.empty()) {
143 for(table_t* p=table;*p->ext;p++) mime.add(sref(p->ext),sref(p->name));
144 }
145 mstring path=file.past_last('.');
146 path.tolower();
147 if(path.nempty()) return mime.get(path);
148 return 0;
149}
diff --git a/src/mime/enc.h b/src/mime/enc.h
new file mode 100644
index 0000000..a6ec57a
--- /dev/null
+++ b/src/mime/enc.h
@@ -0,0 +1,36 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef ENCMIMEH
21#define ENCMIMEH
22
23#include <mime/pack.h>
24
25const mstring trans_base64="base64";
26const mstring trans_quote="quoted-printable";
27const mstring mime_default="iso-8859-1";
28
29void decode64(mstream& out,const sref& in);
30void encode64(mstream& out,const sref& in);
31void decodeQP(mstream& out,const sref& in);
32void encodeQP(mstream& out,const sref& in);
33void decodeHeader(mstream& out,mstring& mime,const sref& in);
34void encodeHeader(mstream& out,const sref& mime,const sref& in);
35
36#endif
diff --git a/src/mime/mailbox.cc b/src/mime/mailbox.cc
new file mode 100644
index 0000000..69f8140
--- /dev/null
+++ b/src/mime/mailbox.cc
@@ -0,0 +1,137 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/mailbox.h>
21
22static int FromHead(const sref& body)
23{
24 sref tag,from,rest=body;
25 Split(tag,rest);
26 Split(from,rest);
27 return tag==from_tag&&htcTime(0,rest)>=0;
28}
29
30/////////////////////////////////////////////////////////////////////
31
32const mstring nextmsg_tag="\nFrom ";
33const mstring sep_tag="--";
34
35Message::Message()
36{
37}
38
39int Message::Special(sref line)
40{
41 line=Rest(line);
42 from=from0=First(line);
43 date=Rest(line);
44 idate=htcTime(0,date);
45 return idate>=0;
46}
47
48int Message::Handle(const sref& name,
49 const sref& rawval,
50 const sref& val,
51 const rrpile& opts)
52{
53 mstring mime;
54 if(Mime::Handle(name,rawval,val,opts)) return 1;
55 else if(eqn(name,from_tag)) {
56 swrite sw(from);
57 decodeHeader(sw,mime,rawval);
58 }
59 else if(eqn(name,subject_tag)) {
60 swrite sw(subject);
61 decodeHeader(sw,mime,rawval);
62 }
63 else if(eqn(name,to_tag)) {
64 swrite sw(to);
65 decodeHeader(sw,mime,rawval);
66 }
67 else if(eqn(name,msgid_tag)) msgid=rawval;
68 else if(eqn(name,received_tag)) received.push_back(rawval);
69 else return 0;
70 return 1;
71}
72
73void Message::putHead(mstream& out) const
74{
75 if(from0.nempty()) { out<<"From "<<from0<<" "<<date<<"\r\n"; }
76 if(putval(out,from_tag,from)) putend(out);
77 if(putval(out,subject_tag,subject)) putend(out);
78 if(putval(out,to_tag,to)) putend(out);
79 if(putval(out,msgid_tag,msgid)) putend(out);
80 for(spile::const_iterator p=received.begin();p!=received.end();p++)
81 if(putval(out,received_tag,*p)) putend(out);
82 Mime::putHead(out);
83}
84
85///////////////////////////////////////////////////////////////
86
87void AppendMessage(FILE* fp,const sref& msg)
88{
89 fwrite(msg.data(),1,msg.size(),fp);
90}
91
92void AppendMessages(FILE* fp,const Mailbox& box)
93{
94 for(int i=0;i<box.size();i++) AppendMessage(fp,box[i]);
95}
96
97int PutMessages(const Mailbox& box,const mstring& path)
98{
99 FILE* fp=fopen(path.c_str(),"w+");
100 if(!fp) return 0;
101 AppendMessages(fp,box);
102 return fclose(fp)==0;
103}
104
105int AppendMessages(const Mailbox& box,const mstring& path)
106{
107 FILE* fp=fopen(path.c_str(),"a+");
108 if(!fp) return 0;
109 AppendMessages(fp,box);
110 return fclose(fp)==0;
111}
112
113///////////////////////////////////////////////////////////////
114
115int GetMessages(Mailbox& box,const mstring& path)
116{
117 mstring buffer; if(buffer.load(path)<0) return -1;
118 sref next,rest=buffer;
119 int old=box.size();
120 while(rest.nempty()) {
121 Message msg(rest);
122 if(msg.from0.empty()) break; // should not happen, I guess
123
124 if(msg.cont_length.nempty())
125 next=msg.body.right(atoi(msg.cont_length));
126 else if(msg.cont_type_boundary.nempty())
127 next=msg.body.past_first(sep_tag+msg.cont_type_boundary+sep_tag).right_first(nextmsg_tag).popf();
128 else
129 next=rest.right_first(nextmsg_tag).popf();
130
131 box.push_back(rest.left(next-rest));
132
133 rest=next.right_first_not_of(cset_ws);
134 while(rest.nempty()&&!FromHead(rest)) rest=rest.right_first(nextmsg_tag).popf();
135 }
136 return box.size()-old;
137}
diff --git a/src/mime/mailbox.h b/src/mime/mailbox.h
new file mode 100644
index 0000000..3e5838c
--- /dev/null
+++ b/src/mime/mailbox.h
@@ -0,0 +1,60 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MAILBOXH
21#define MAILBOXH
22
23#include <mime/mime.h>
24#include <mt/dates.h>
25
26const mstring from_tag="From";
27const mstring to_tag="To";
28const mstring subject_tag="Subject";
29const mstring msgid_tag="Message-ID";
30const mstring received_tag="Received";
31
32class Message : public Mime {
33public:
34 Message();
35 Message(const sref& msg) { Init(msg); }
36
37 mstring from0,from,date,subject,to,msgid;
38 spile received;
39 time_t idate;
40
41 void putHead(mstream& out) const;
42protected:
43 int Special(sref line);
44 int Handle(const sref& name,
45 const sref& rawval,
46 const sref& val,
47 const rrpile& opts);
48};
49
50typedef msvec<mstring> Mailbox;
51
52void AppendMessage(FILE* fp,const sref& msg);
53void AppendMessages(FILE* fp,const Mailbox& box);
54
55int PutMessages(const Mailbox& box,const mstring& path);
56int AppendMessages(const Mailbox& box,const mstring& path);
57
58int GetMessages(Mailbox& box,const mstring& path);
59
60#endif
diff --git a/src/mime/mime.cc b/src/mime/mime.cc
new file mode 100644
index 0000000..a7a1884
--- /dev/null
+++ b/src/mime/mime.cc
@@ -0,0 +1,188 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/mime.h>
21
22const charset par_left("([{"),par_right("}])");
23
24inline int is_field(const sref& s) {
25 sref p=s.left_first(':');
26 while(cset_spaces.test(p.back())) p=p.popb();
27 return p.nempty()&&p.find_of(cset_spaces)<0;
28}
29
30inline int getquoted(const sref& s,char c) {
31 int i,quote=0,par=0;
32 for(i=0;i<s.size();i++) {
33 if(s[i]=='\"') quote=!quote;
34 else if(par_left.test(s[i])) par++;
35 else if(par_right.test(s[i])) par--;
36 else if(s[i]==c&&!quote&&!par) break;
37 }
38 return i;
39}
40
41void Mime::Init(const sref& message)
42{
43 mstring line;
44 rrpile pile;
45 sref first;
46 head=body=message;
47 while(Splitln(first,body)) {
48 if(first.empty()) break;
49 if(!is_field(first)) Special(first);
50 else {
51 line=first;
52 while(cset_spaces.test(*body)) {
53 Splitln(first,body);
54 line.append(1,' ');
55 line+=first.right_first_not_of(cset_spaces);
56 }
57 sref opt=line;
58 int col=opt.find(':');
59 sref name=Trim(opt.left(col),cset_quotes);
60 opt=opt.adv(col).popf();
61 sref rawval=Trim(opt);
62 int semi=getquoted(opt,';');
63 sref val=Trim(opt.left(semi),cset_quotes);
64 if(getquoted(val,'=')<val.size()) val.clear();
65 else opt=opt.adv(semi).popf();
66 pile.clear();
67 while(opt.nempty()) {
68 sref optname=opt.left(getquoted(opt,'='));
69 opt=opt.adv(optname).popf();
70 semi=getquoted(opt,';');
71 sref optval=opt.left(semi);
72 opt=opt.adv(semi).popf();
73 optname=Trim(optname,cset_quotes);
74 optval=Trim(optval,cset_quotes);
75 if(optname.nempty()) pile.push_back(rrstring(optname,optval));
76 }
77 Handle(name,rawval,val,pile);
78 }
79 }
80 head=head.left(body-head);
81}
82
83
84///////////////////////////////////////////////////////////////////////////
85
86Mime::Mime()
87{
88 mime_version="1.0";
89}
90
91int Mime::Special(sref line)
92{
93 return 0;
94}
95
96int Mime::Handle(const sref& name,
97 const sref& rawval,
98 const sref& val,
99 const rrpile& opts) {
100 if(eqn(name,mime_version_tag)) mime_version=val;
101 else if(eqn(name,cont_type_tag)) {
102 (cont_type=val).tolower();
103 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++) {
104 if(eqn(p->first,charset_tag)) cont_type_charset=p->second;
105 else if(eqn(p->first,name_tag)) cont_type_name=p->second;
106 else if(eqn(p->first,boundary_tag)) cont_type_boundary=p->second;
107 }
108 }
109 else if(eqn(name,cont_id_tag)) cont_id=val;
110 else if(eqn(name,cont_desc_tag)) cont_desc=val;
111 else if(eqn(name,cont_disp_tag)) {
112 cont_disp=val;
113 for(rrpile::const_iterator p=opts.begin();p!=opts.end();p++) {
114 if(eqn(p->first,name_tag)) cont_disp_name=p->second;
115 else if(eqn(p->first,file_tag)) cont_disp_file=p->second;
116 }
117 }
118 else if(eqn(name,cont_trans_enc_tag)) cont_trans_enc=val;
119 else if(eqn(name,cont_length_tag)) cont_length=val;
120 else return 0;
121 return 1;
122}
123
124///////////////////////////////////////////////////////////////////////////
125
126void Mime::putHead(mstream& out) const
127{
128 if(putval(out,mime_version_tag,mime_version)) putend(out);
129 if(putval(out,cont_type_tag,cont_type)) {
130 putopt(out,charset_tag,cont_type_charset);
131 putopt(out,name_tag,cont_type_name);
132 putopt(out,boundary_tag,cont_type_boundary);
133 putend(out);
134 }
135 if(putval(out,cont_id_tag,cont_id)) putend(out);
136 if(putval(out,cont_desc_tag,cont_desc)) putend(out);
137 if(putval(out,cont_disp_tag,cont_disp)) {
138 putopt(out,name_tag,cont_disp_name);
139 putopt(out,file_tag,cont_disp_file);
140 putend(out);
141 }
142 if(putval(out,cont_trans_enc_tag,cont_trans_enc)) putend(out);
143 if(putval(out,cont_length_tag,cont_length)) putend(out);
144}
145
146
147///////////////////////////////////////////////////////////////////////////
148
149int Mime::Multipart(rpile& list) const
150{
151 if(cont_type_boundary.empty()) return 0;
152 mstring bound=sref("--")+cont_type_boundary;
153 sref rest=body.past_first(bound).past_nl();
154 while(rest.nempty()) {
155 int pos=rest.find(bound);
156 if(pos>=0) {
157 sref first=rest.left(pos);
158 if(first.back()=='\n') {
159 first=first.popb();
160 if(first.back()=='\r') first=first.popb();
161 }
162 list.push_back(first);
163 rest=rest.right(pos).adv(bound.size());
164 if(*rest=='-') rest.clear(); else rest=rest.past_nl();
165 }
166 else {
167 list.push_back(rest);
168 rest.clear();
169 }
170 }
171 return !list.empty();
172}
173
174void Mime::Pick(const sref& mime)
175{
176 rpile list;
177 if(Multipart(list)) {
178 if(eqn(cont_type,mime_multialt)) {
179 int pos=0;
180 for(int i=0;i<list.size();i++) {
181 Mime msg(list[i]);
182 if(eqn(msg.cont_type,mime)) { pos=i; break; }
183 }
184 Init(list[pos]);
185 }
186 }
187}
188
diff --git a/src/mime/mime.h b/src/mime/mime.h
new file mode 100644
index 0000000..fb2ae0f
--- /dev/null
+++ b/src/mime/mime.h
@@ -0,0 +1,99 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MIMEH
21#define MIMEH
22
23#include <mime/enc.h>
24
25// MIME Headers
26const mstring mime_version_tag="MIME-Version";
27const mstring cont_type_tag="Content-Type";
28const mstring cont_trans_enc_tag="Content-Transfer-Encoding";
29const mstring cont_id_tag="Content-ID";
30const mstring cont_desc_tag="Content-Description";
31const mstring cont_disp_tag="Content-Disposition";
32const mstring cont_length_tag="Content-Length";
33// Option headers
34const mstring name_tag="name";
35const mstring file_tag="filename";
36const mstring charset_tag="charset";
37const mstring boundary_tag="boundary";
38const mstring path_tag="path";
39// Some Content types
40const mstring mime_textplain="text/plain";
41const mstring mime_texthtml="text/html";
42const mstring mime_texthtc="text/x-htc";
43const mstring mime_multialt="multipart/alternative";
44
45/////////////////////////////////////////////////////////////////
46
47const sref* file2mime(const sref& file);
48
49/////////////////////////////////////////////////////////////////
50
51class Mime {
52public:
53 sref head,body;
54
55 mstring mime_version;
56 mstring cont_type,cont_type_charset,cont_type_name,cont_type_boundary;
57 mstring cont_id;
58 mstring cont_desc;
59 mstring cont_disp,cont_disp_name,cont_disp_file;
60 mstring cont_trans_enc;
61 mstring cont_length;
62
63 virtual void putHead(mstream& out) const;
64
65 void Init(const sref& in);
66
67 int Multipart(rpile& list) const;
68 void Pick(const sref& mime);
69
70 Mime();
71 Mime(const sref& msg) { Init(msg); }
72
73protected:
74 virtual int Special(sref line);
75 virtual int Handle(const sref& name,
76 const sref& rawval,
77 const sref& val,
78 const rrpile& opts);
79};
80
81//////////////////////////////////////////////////////////////////
82
83inline int putval(mstream& out,const sref& tag,const sref& val) {
84 if(val.nempty()) { out<<tag<<": "<<val; return 1; } else return 0;
85}
86inline void putopt(mstream& out,const sref& tag,const sref& val) {
87 if(val.nempty()) out<<"; "<<tag<<"=\""<<val<<"\"";
88}
89inline int putopt1(mstream& out,const sref& tag,const sref& val) {
90 if(val.nempty()) { out<<tag<<"=\""<<val<<"\""; return 1; } else return 0;
91}
92inline int putopt2(mstream& out,const sref& tag,const sref& val) {
93 if(val.nempty()) { out<<tag<<"="<<val; return 1; } else return 0;
94}
95inline void putend(mstream& out) { out<<CRLF; }
96
97//////////////////////////////////////////////////////////////////
98
99#endif
diff --git a/src/mime/pack.cc b/src/mime/pack.cc
new file mode 100644
index 0000000..78fde26
--- /dev/null
+++ b/src/mime/pack.cc
@@ -0,0 +1,143 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/pack.h>
21
22const char hex2char[16]={
23 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
24};
25const unsigned char2hex[256]={
26 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
27 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
28 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
29 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
30 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
31 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
32 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
33 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
34};
35
36mstream& cashex(mstream& out,unsigned char c) {
37 return out.put(hex2char[c>>4]).put(hex2char[c&15]);
38}
39char hexasc(unsigned char c1,unsigned char c2) {
40 return ((char2hex[c1]<<4)|char2hex[c2]);
41}
42
43void Pack(mstream& out,const sref& s)
44{
45 static const charset escaped("&=%+\"'? ");
46 static const charset conv=~cset_printable|escaped;
47 sref q,p=s;
48 while(p.nempty()) {
49 p=p.adv(q=p.left_first_of(conv));
50 out<<q;
51 while(conv.test(p.front())) {
52 char c=*p; p=p.popf();
53 if(c==' ') out.put('+');
54 else {
55 out.put('%');
56 cashex(out,c);
57 }
58 }
59 }
60}
61
62void Pack(mstream& out,const rpile& list)
63{
64 for(rpile::const_iterator p=list.begin();p!=list.end();++p) {
65 Pack(out,*p);
66 out.put('&');
67 }
68}
69
70void Pack(mstream& out,const rrpile& list)
71{
72 for(rrpile::const_iterator p=list.begin();p!=list.end();++p) {
73 Pack(out,p->first);
74 out.put('=');
75 Pack(out,p->second);
76 out.put('&');
77 }
78}
79
80///////////////////////////////////////////////////////////////
81
82void Unpack(mstream& out,const sref& in)
83{
84 static const charset tags("%+");
85 sref e,p=in;
86 while(p.nempty()) {
87 p=p.adv(e=p.left_first_of(tags));
88 out<<e;
89 while(tags.test(p.front())) {
90 char c=*p; p=p.popf();
91 if(c=='+') out.put(' ');
92 else if(c=='%') {
93 unsigned char c1=p[0],c2=p[1]; p=p.adv(2);
94 out.put(hexasc(c1,c2));
95 }
96 else out.put(c);
97 }
98 }
99}
100
101void Unpack(spile& list,const sref& in)
102{
103 sref e,p=in;
104 while(p.nempty()) {
105 p=p.adv(e=p.left_first('&')).popf();
106 if(e.nempty()) {
107 list.push_back(mstring());
108 swrite sw(list.back());
109 Unpack(sw,e);
110 }
111 }
112}
113
114void Unpack(sspile& list,const sref& in)
115{
116 sref e1,e2,p=in;
117 while(p.nempty()) {
118 p=p.adv(e1=p.left_first('=')).popf();
119 if(e1.nempty()) {
120 p=p.adv(e2=p.left_first('&')).popf();
121 list.push_back(sstring());
122 swrite sw1(list.back().first);
123 Unpack(sw1,e1);
124 swrite sw2(list.back().second);
125 Unpack(sw2,e2);
126 }
127 }
128}
129
130///////////////////////////////////////////////////////////////
131
132void CRLF2LF(mstream& out,const sref& in)
133{
134 sref first,rest=in;
135 while(Splitln(first,rest)) out<<first<<"\n";
136}
137
138void LF2CRLF(mstream& out,const sref& in)
139{
140 sref first,rest=in;
141 while(Splitln(first,rest)) out<<first<<CRLF;
142}
143
diff --git a/src/mime/pack.h b/src/mime/pack.h
new file mode 100644
index 0000000..e750aac
--- /dev/null
+++ b/src/mime/pack.h
@@ -0,0 +1,48 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef PACKH
21#define PACKH
22
23#include <mt/mset.h>
24#include <mt/msmap.h>
25
26// Really mimefunctions, but needed here
27
28mstream& cashex(mstream& out,unsigned char c);
29char hexasc(unsigned char c1,unsigned char c2);
30
31// Packing means application/x-www-form-urlencoded
32
33void Unpack(mstream& out,const sref& in);
34void Unpack(spile& list,const sref& in);
35void Unpack(sspile& list,const sref& in);
36
37void Pack(mstream& out,const sref& in);
38void Pack(mstream& out,const rpile& list);
39void Pack(mstream& out,const rrpile& list);
40
41// CR LF and CRLF business
42
43const mstring CRLF="\r\n";
44
45void CRLF2LF(mstream& out,const sref& in);
46void LF2CRLF(mstream& out,const sref& in);
47
48#endif
diff --git a/src/mime/qp.cc b/src/mime/qp.cc
new file mode 100644
index 0000000..78dc36f
--- /dev/null
+++ b/src/mime/qp.cc
@@ -0,0 +1,150 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/enc.h>
21#include <mime/pack.h>
22#include <algorithm>
23
24const charset special("=\"#$\\^`{|}~");
25//const charset special("=!\"#$@[\\]^`{|}~");
26const charset headspecial("_?");
27const charset printable=cset_printable&~special;
28const charset printhead=printable&~headspecial;
29const mstring beg_tag("=?"),end_tag("?=");
30const mstring enc_qp_tag("Q"),enc_64_tag("B");
31const int WRAPAT=76;
32const int HEADWRAP=WRAPAT-7;
33
34void decodeQP(mstream& out,const sref& in)
35{
36 const char* p=in.begin();
37 while(p<in.end()) {
38 unsigned char c=*p++;
39 if(c=='=') {
40 if(cset_ws.test(*p)) p=in(p).past_nl().data();
41 else {
42 unsigned char c1=*p++,c2=*p++;
43 out.put(hexasc(c1,c2));
44 }
45 }
46 else out.put(c);
47 }
48}
49
50void encodeQP(mstream& out,const sref& in)
51{
52 sref first,rest=in;
53 while(Splitln(first,rest)) {
54 int n=0;
55 const char* p=first.begin();
56 while(p<first.end()) {
57 unsigned char c=*p++;
58 if(printable.test(c)) {
59 if(first(p).empty()&&cset_spaces.test(c)) { cashex(out.put('='),c); n+=3; }
60 else { out.put(c); n++; }
61 }
62 else { cashex(out.put('='),c); n+=3; }
63 if(first(p).nempty()&&n>=WRAPAT) { out.put('=')<<CRLF; n=0; }
64 }
65 out<<CRLF;
66 }
67}
68
69static void decodeHQ(mstream& out,const sref& in)
70{
71 const char* p=in.begin();
72 while(p<in.end()) {
73 unsigned char c=*p++;
74 if(c=='=') {
75 unsigned char c1=*p++,c2=*p++;
76 out.put(hexasc(c1,c2));
77 }
78 else if(c=='_') out.put(' ');
79 else out.put(c);
80 }
81}
82
83static int encodeHQ(mstream& out,const sref& in)
84{
85 int enc=0;
86 const char* p=in.begin();
87 while(p<in.end()) {
88 unsigned char c=*p++;
89 if(!printable.test(c)) enc=1;
90 if(printhead.test(c)) { if(c==32) out.put('_'); else out.put(c); }
91 else cashex(out.put('='),c);
92 }
93 return enc;
94}
95
96void decodeHeader(mstream& out,mstring& mime,const sref& in)
97{
98 sref e,p=in;
99 while(p.nempty()) {
100 p=p.adv(e=p.left_first(beg_tag));
101 out<<e;
102 if(p.nempty()) {
103 p=p.adv(beg_tag.size());
104 mime=p.left_first('?');
105 p=p.adv(mime.size());
106 if(p.empty()) { out<<beg_tag<<mime; p.clear(); }
107 else {
108 p=p.popf();
109 sref enc=p.left_first('?');
110 p=p.adv(enc);
111 if(p.empty()) { out<<beg_tag<<mime<<"?"<<enc; p.clear(); }
112 else {
113 p=p.adv(e=p.popf().left_first(end_tag));
114 if(p.empty()) { out<<beg_tag<<mime<<"?"<<enc<<"?"<<e; p.clear(); }
115 else {
116 p=p.adv(end_tag.size());
117 if(eqn(enc,enc_qp_tag)) decodeHQ(out,e);
118 else if(eqn(enc,enc_64_tag)) decode64(out,e);
119 else out<<"BAD: ["<<mime<<"]["<<enc<<"]["<<e<<"]";
120 }
121 }
122 }
123 }
124 }
125}
126
127void encodeHeader(mstream& out,const sref& mime,const sref& in)
128{
129 mstring tmp;
130 swrite sw(tmp);
131 if(encodeHQ(sw,in)) {
132 int wrapat=HEADWRAP-mime.size();
133 sref e,p=tmp;
134 p=p.adv(e=p.left(std::min(wrapat,p.size())));
135 out<<beg_tag<<mime<<"?Q?"<<e<<end_tag;
136 while(p.nempty()) {
137 p=p.adv(e=p.left(std::min(wrapat,p.size())));
138 out<<"\r\n\t"<<beg_tag<<mime<<"?Q?"<<e<<end_tag;
139 }
140 }
141 else {
142 sref e,p=in;
143 p=p.adv(e=p.left(std::min(WRAPAT,p.size())));
144 out<<e;
145 while(p.nempty()) {
146 p=p.adv(e=p.left(std::min(WRAPAT,p.size())));
147 out<<"\r\n\t"<<e;
148 }
149 }
150}
diff --git a/src/mime/test.cc b/src/mime/test.cc
new file mode 100644
index 0000000..6392904
--- /dev/null
+++ b/src/mime/test.cc
@@ -0,0 +1,108 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mime/mailbox.h>
21#include <mime/mime.h>
22#include <mime/enc.h>
23#include <sys/stat.h>
24
25static fp_stream mout(stdout),merr(stderr);
26
27static void Show(mstream& out,const Message& msg)
28{
29 if(msg.cont_type.empty()||
30 eqn(msg.cont_type,mime_textplain)||
31 eqn(msg.cont_type,mime_texthtml)) {
32 if(eqn(msg.cont_trans_enc,trans_quote)) {
33 //decodeQP(out,msg.body);
34 mswrite tmp;
35 decodeQP(tmp,msg.body);
36 encodeQP(out,tmp.str());
37 }
38 else {
39 //out<<msg.body<<"\n";
40 encodeQP(out,msg.body);
41 }
42 }
43 else out<<"(not shown)\n";
44}
45
46main(int argc,char* argv[])
47{
48 if(argc<2) {
49 merr<<"Usage: "<<argv[0]<<" <source> [index]\n";
50 return 1;
51 }
52 Mailbox box;
53 GetMessages(box,argv[1]);
54 merr<<"Found "<<box.size()<<" messages\n";
55 if(argc>2) {
56 Message msg(box[atoi(argv[2])]);
57 //msg.Pick(mime_textplain);
58
59 mswrite tmp;
60 encodeHeader(tmp,mime_default,msg.subject);
61 msg.subject=tmp.str();
62
63 msg.putHead(mout);
64 mout<<"-----------------------------------------\n";
65 rpile part;
66 if(msg.Multipart(part)) {
67 for(int i=0;i<part.size();i++) {
68 Message pm(part[i]);
69 pm.putHead(mout);
70 mout<<"-------------------------------\n";
71 Show(mout,pm);
72 mout<<"-------------------------------\n";
73 }
74 }
75 else {
76 Show(mout,msg);
77 }
78
79 mout<<"**********\n";
80 mout<<msg.head;
81 mout<<"**********\n";
82 mout<<msg.body;
83 mout<<"**********\n";
84
85 }
86
87 return 0;
88}
89
90/*
91main(int argc,char* argv[])
92{
93 if(argc<2) {
94 merr<<"Usage: "<<argv[0]<<" <source>\n";
95 return 1;
96 }
97 mstring buffer; buffer.load(argv[1]);
98 merr<<buffer.size()<<"\n";
99 mswrite enc;
100 encode64(enc,buffer);
101 merr<<enc.str().size()<<"\n";
102 mswrite nbuf;
103 decode64(nbuf,enc.str());
104 merr<<nbuf.str().size()<<"\n";
105 if(nbuf.str()==buffer) merr<<"Match.\n";
106 mout<<enc.str();
107}
108*/
diff --git a/src/mt/cfind.f b/src/mt/cfind.f
new file mode 100644
index 0000000..3d101ec
--- /dev/null
+++ b/src/mt/cfind.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function cfind(s,n,c)
21 character s(0:1),c
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=0,m-1
25 if(s(i).eq.c)go to 100
26 10 continue
27 do 20 i=m,n-1,16
28 if(s(i).eq.c)go to 100
29 if(s(i+1).eq.c)go to 101
30 if(s(i+2).eq.c)go to 102
31 if(s(i+3).eq.c)go to 103
32 if(s(i+4).eq.c)go to 104
33 if(s(i+5).eq.c)go to 105
34 if(s(i+6).eq.c)go to 106
35 if(s(i+7).eq.c)go to 107
36 if(s(i+8).eq.c)go to 108
37 if(s(i+9).eq.c)go to 109
38 if(s(i+10).eq.c)go to 110
39 if(s(i+11).eq.c)go to 111
40 if(s(i+12).eq.c)go to 112
41 if(s(i+13).eq.c)go to 113
42 if(s(i+14).eq.c)go to 114
43 if(s(i+15).eq.c)go to 115
44 20 continue
45 cfind=-1
46 return
47 100 cfind=i
48 return
49 101 cfind=i+1
50 return
51 102 cfind=i+2
52 return
53 103 cfind=i+3
54 return
55 104 cfind=i+4
56 return
57 105 cfind=i+5
58 return
59 106 cfind=i+6
60 return
61 107 cfind=i+7
62 return
63 108 cfind=i+8
64 return
65 109 cfind=i+9
66 return
67 110 cfind=i+10
68 return
69 111 cfind=i+11
70 return
71 112 cfind=i+12
72 return
73 113 cfind=i+13
74 return
75 114 cfind=i+14
76 return
77 115 cfind=i+15
78 return
79 end
80
diff --git a/src/mt/charset.h b/src/mt/charset.h
new file mode 100644
index 0000000..84742b9
--- /dev/null
+++ b/src/mt/charset.h
@@ -0,0 +1,131 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef CHARSETH
21#define CHARSETH
22
23#include <string.h>
24
25struct charset {
26 explicit charset(const char s[]) {
27 memset(negmap,0,256); while(*s) map[*s++]=1;
28 }
29 charset(char beg,char end) {
30 memset(negmap,0,256); while(beg<=end) map[beg++]=1;
31 }
32 int test(char c) const { return map[c]; }
33 int operator[](char c) const { return map[c]; }
34 char negmap[128],map[128];
35};
36
37inline charset operator|(const charset& a,const charset& b) {
38 charset c(a); for(int i=-127;i<128;i++) c.map[i]|=b.map[i]; return c;
39}
40inline charset operator|(const charset& a,char b) {
41 charset c(a); c.map[b]=(b!=0); return c;
42}
43inline charset operator|(char a,const charset& b) {
44 charset c(b); c.map[a]=(a!=0); return c;
45}
46inline charset operator&(const charset& a,const charset& b) {
47 charset c(a); for(int i=-127;i<128;i++) c.map[i]&=b.map[i]; return c;
48}
49inline charset operator^(const charset& a,const charset& b) {
50 charset c(a); for(int i=-127;i<128;i++) c.map[i]^=b.map[i]; return c;
51}
52inline charset operator-(const charset& a,const charset& b) {
53 charset c(a); for(int i=-127;i<128;i++) c.map[i]&=~b.map[i]; return c;
54}
55inline charset operator-(const charset& a,char b) {
56 charset c(a); c.map[b]=0; return c;
57}
58inline charset operator~(const charset& a) {
59 charset c(a); for(int i=-127;i<128;i++) c.map[i]=!c.map[i]; c.map[0]=0;
60 return c;
61}
62
63//////////////////////////////////////////////////////////////////////////
64
65struct charmap {
66 charmap() { for(int i=-127;i<128;i++) map[i]=i; }
67 charmap(const charset& a,const charset& b) {
68 for(int i=-127,j=-127;i<128;i++) {
69 if(a[i]) { while(j<128&&!b[j]) j++; map[i]=j++; }
70 else map[i]=i;
71 }
72 }
73 charmap(const charset& a,const char* b) {
74 for(int i=-127;i<128;i++) if(a[i]&&*b) map[i]=*b++; else map[i]=i;
75 }
76 char operator[](char c) const { return map[c]; }
77 char negmap[128],map[128];
78};
79
80inline charmap operator<<(const charmap& a,const charmap& b) {
81 charmap c(a);
82 for(int i=-127;i<128;i++) if(b.map[i]!=i) c.map[i]=b.map[i];
83 for(int i=-127;i<128;i++) c.map[i]=c.map[c.map[i]];
84 return c;
85}
86
87//////////////////////////////////////////////////////////////////////////
88
89struct bracket {
90 explicit bracket(const char s[]) { strncpy(&left,s,sizeof(bracket)); }
91 int test(char c) const { return c==left||c==right; }
92 char left,right,esc,end;
93};
94
95//////////////////////////////////////////////////////////////////////////
96
97const charset cset_spaces(" \t");
98const charset cset_newl("\r\n");
99const charset cset_ws=cset_spaces|cset_newl;
100const charset cset_printable(' ','~');
101const charset cset_digit('0','9');
102const charset cset_real=cset_digit|'.';
103const charset cset_sign("+-");
104const charset cset_lalpha('a','z');
105const charset cset_ualpha('A','Z');
106const charset cset_alpha=cset_lalpha|cset_ualpha;
107const charset cset_alphanum=cset_alpha|cset_digit;
108const charset cset_alphareal=cset_alpha|cset_real;
109const charset cset_lext1(-32,-10),cset_lext2(-8,-2);
110const charset cset_uext1(-64,-42),cset_uext2(-40,-34);
111const charset cset_liso=cset_lalpha|cset_lext1|cset_lext2;
112const charset cset_uiso=cset_ualpha|cset_uext1|cset_uext2;
113
114const charmap cset_ident;
115const charmap cset_leqv1(cset_lext1,"aaaaaaaceeeeiiiidnooooo");
116const charmap cset_leqv2(cset_lext2,"ouuuuyp");
117const charmap cset_ueqv1(cset_uext1,"AAAAAAACEEEEIIIIDNOOOOO");
118const charmap cset_ueqv2(cset_uext2,"OUUUUYP");
119
120const charmap cset_lcase(cset_uiso,cset_liso);
121const charmap cset_ucase(cset_liso,cset_uiso);
122const charmap cset_sim=cset_lcase<<cset_leqv1<<cset_leqv2;
123
124const bracket cset_quotes("\"\"\\");
125const bracket cset_indices("[]\\");
126const bracket cset_braces("{}\\");
127const bracket cset_para("()\\");
128const bracket cset_dollars("$$\\");
129const bracket cset_hooks("<>\\");
130
131#endif
diff --git a/src/mt/config.cc b/src/mt/config.cc
new file mode 100644
index 0000000..1797780
--- /dev/null
+++ b/src/mt/config.cc
@@ -0,0 +1,33 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/config.h>
21
22mstring htchome()
23{
24 const char* p=getenv("HTCHOME");
25 if(!p) {
26 fprintf(stderr,"env: HTCHOME not set, exiting\n");
27 exit(-1);
28 }
29 mstring home=p;
30 if(home.back()=='/') home=home.popb();
31 return home;
32}
33
diff --git a/src/mt/config.h b/src/mt/config.h
new file mode 100644
index 0000000..5389755
--- /dev/null
+++ b/src/mt/config.h
@@ -0,0 +1,27 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef CONFIGH
21#define CONFIGH
22
23#include <mt/mstring.h>
24
25mstring htchome();
26
27#endif
diff --git a/src/mt/crfind.f b/src/mt/crfind.f
new file mode 100644
index 0000000..f996ac4
--- /dev/null
+++ b/src/mt/crfind.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function crfind(s,n,c)
21 character s(0:1),c
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=n-16,m,-16
25 if(s(i+15).eq.c)go to 115
26 if(s(i+14).eq.c)go to 114
27 if(s(i+13).eq.c)go to 113
28 if(s(i+12).eq.c)go to 112
29 if(s(i+11).eq.c)go to 111
30 if(s(i+10).eq.c)go to 110
31 if(s(i+9).eq.c)go to 109
32 if(s(i+8).eq.c)go to 108
33 if(s(i+7).eq.c)go to 107
34 if(s(i+6).eq.c)go to 106
35 if(s(i+5).eq.c)go to 105
36 if(s(i+4).eq.c)go to 104
37 if(s(i+3).eq.c)go to 103
38 if(s(i+2).eq.c)go to 102
39 if(s(i+1).eq.c)go to 101
40 if(s(i).eq.c)go to 100
41 10 continue
42 do 20 i=m-1,0,-1
43 if(s(i).eq.c)go to 100
44 20 continue
45 crfind=-1
46 return
47 100 crfind=i
48 return
49 101 crfind=i+1
50 return
51 102 crfind=i+2
52 return
53 103 crfind=i+3
54 return
55 104 crfind=i+4
56 return
57 105 crfind=i+5
58 return
59 106 crfind=i+6
60 return
61 107 crfind=i+7
62 return
63 108 crfind=i+8
64 return
65 109 crfind=i+9
66 return
67 110 crfind=i+10
68 return
69 111 crfind=i+11
70 return
71 112 crfind=i+12
72 return
73 113 crfind=i+13
74 return
75 114 crfind=i+14
76 return
77 115 crfind=i+15
78 return
79 end
80
diff --git a/src/mt/dates.cc b/src/mt/dates.cc
new file mode 100644
index 0000000..8c244e5
--- /dev/null
+++ b/src/mt/dates.cc
@@ -0,0 +1,207 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/dates.h>
21#include <mt/split.h>
22#include <ctype.h>
23
24const mstring SWEEK[MAXLANG][7]={
25 "Sun","Mon","Tue","Wed","Thu","Fri","Sat",
26 "Sön","Mån","Tis","Ons","Tor","Fre","Lör"
27};
28const mstring SMONTH[MAXLANG][12]={
29 "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",
30 "Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"
31};
32const mstring WEEK[MAXLANG][7]={
33 "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday",
34 "Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"
35};
36const mstring MONTH[MAXLANG][12]={
37 "January","February","March","April","May","June",
38 "July","August","September","October","November","December",
39 "Januari","Februari","Mars","April","Maj","Juni",
40 "Juli","Augusti","September","Oktober","November","December"
41};
42
43time_t Today(time_t now)
44{
45 tm s; localtime_r(&now,&s);
46 s.tm_hour=0;
47 s.tm_min=0;
48 s.tm_sec=0;
49 return mktime(&s);
50}
51
52time_t Sunday(time_t now)
53{
54 tm s; localtime_r(&now,&s);
55 s.tm_mday-=s.tm_wday;
56 return mktime(&s);
57}
58
59const mstring& Week(int lang,time_t t)
60{
61 tm s; return WEEK[lang][localtime_r(&t,&s)->tm_wday];
62}
63
64const mstring& Month(int lang,time_t t)
65{
66 tm s; return MONTH[lang][localtime_r(&t,&s)->tm_mon];
67}
68
69const mstring& SWeek(int lang,time_t t)
70{
71 tm s; return SWEEK[lang][localtime_r(&t,&s)->tm_wday];
72}
73
74const mstring& SMonth(int lang,time_t t)
75{
76 tm s; return SMONTH[lang][localtime_r(&t,&s)->tm_mon];
77}
78
79mstring httpTime(time_t t)
80{
81 tm tt; gmtime_r(&t,&tt);
82 return mstring().convert("%s, %02d %s %4d %02d:%02d:%02d GMT",
83 SWEEK[0][tt.tm_wday].c_str(),
84 tt.tm_mday,
85 SMONTH[0][tt.tm_mon].c_str(),
86 tt.tm_year+1900,
87 tt.tm_hour,
88 tt.tm_min,
89 tt.tm_sec);
90}
91
92mstring htcTime(int lang,time_t t)
93{
94 tm tt; localtime_r(&t,&tt);
95 mstring s(32); asctime_r(&tt,s.data()); s.resize(24);
96 if(lang) {
97 for(int i=0;i<7;i++) if(s(0,3)==SWEEK[0][i]) {
98 s.replace(0,3,SWEEK[lang][i]);
99 break;
100 }
101 for(int i=0;i<12;i++) if(s(4,3)==SMONTH[0][i]) {
102 s.replace(4,3,SMONTH[lang][i]);
103 break;
104 }
105 }
106 return s;
107}
108
109static int Month(int& mon,const sref& st)
110{
111 mstring s=st; s.tolower(); s[0]=toupper(s[0]);
112 for(int lang=0;lang<MAXLANG;lang++) {
113 for(int m=0;m<12;m++) if(s==SMONTH[lang][m]) { mon=m; return 1; }
114 }
115 return 0;
116}
117
118static int Week(int& week,const sref& st)
119{
120 mstring s=st; s.tolower(); s[0]=toupper(s[0]);
121 for(int lang=0;lang<MAXLANG;lang++) {
122 for(int w=0;w<7;w++) if(s==SWEEK[lang][w]) { week=w; return 1; }
123 }
124 return 0;
125}
126
127static int Time(int& th,int& tmi,int& ts,const sref& st)
128{
129 static const charset sep_tag(":");
130 sref hour,min,sec,when=st;
131 int h,m,s;
132 if(when.find(':')<0) return 0;
133 Split(hour,when,sep_tag);
134 Split(min,when,sep_tag);
135 Split(sec,when,sep_tag);
136 h=atoi(hour);
137 m=atoi(min);
138 s=atoi(sec);
139 if(h>=0&&h<=24&&m>=0&&m<60&&s>=0&&s<60) { th=h; tmi=m; ts=s; return 1; }
140 return 0;
141}
142
143static int Day(int& day,const sref& s)
144{
145 if(s.find_not_of(cset_digit)>=0) return 0;
146 int d=atoi(s);
147 if(d>0&&d<32) { day=d; return 1; }
148 return 0;
149}
150
151static int Year(int& year,const sref& s)
152{
153 if(s.find_not_of(cset_digit)>=0) return 0;
154 int y=atoi(s);
155 if(y>=32&&y<9999) { year=y; return 1; }
156 return 0;
157}
158
159time_t htcTime(int lang,const sref& date)
160{
161 sref week,month,day,when,year,rest=date;
162 Split(week,rest);
163 Split(month,rest);
164 Split(day,rest);
165 Split(when,rest);
166 Split(year,rest);
167 struct tm t;
168 Time(t.tm_hour,t.tm_min,t.tm_sec,when);
169 t.tm_mday=atoi(day);
170 Month(t.tm_mon,month);
171 t.tm_year=atoi(year)-1900;
172 Week(t.tm_wday,week);
173 t.tm_isdst=-1;
174 return mktime(&t);
175}
176
177time_t cvtTime(const sref& code)
178{
179 time_t now=time(0);
180 tm t; localtime_r(&now,&t);
181 t.tm_hour=0;t.tm_min=0;t.tm_sec=0;
182 //Start with 00:00:00 today
183 sref first,rest=code;
184 int w=0,m=0,d=0,h=0,y=0;
185 while(Split(first,rest)) {
186 if(!w) w=Week(t.tm_wday,first);
187 if(!m) m=Month(t.tm_mon,first);
188 if(!h) h=Time(t.tm_hour,t.tm_min,t.tm_sec,first);
189 if(!d) d=Day(t.tm_mday,first);
190 if(!y) if(y=Year(t.tm_year,first)) t.tm_year-=1900;
191 }
192 t.tm_isdst=-1;
193 return mktime(&t);
194}
195
196//////////////////////////////
197
198int Language(const sref& st)
199{
200 static const charset seps=cset_ws|charset(",;");
201 mstring s=st; s.tolower();
202 sref first,rest=s;
203 while(Split(first,rest,seps)) {
204 for(int i=0;i<MAXLANG;i++) if(first==LANG[i]) return i;
205 }
206 return -1;
207}
diff --git a/src/mt/dates.h b/src/mt/dates.h
new file mode 100644
index 0000000..fe05245
--- /dev/null
+++ b/src/mt/dates.h
@@ -0,0 +1,49 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef DATESH
21#define DATESH
22
23#include <mt/mstring.h>
24#include <time.h>
25
26const time_t SEC_PER_DAY=86400;
27const int MAXLANG=2;
28const mstring LANG[MAXLANG]={"en","sv"};
29
30inline time_t Now() { return time(0); }
31inline time_t Days(int days) { return days*SEC_PER_DAY; }
32
33time_t Today(time_t);
34time_t Sunday(time_t);
35
36const mstring& Week(int lang,time_t t);
37const mstring& Month(int lang,time_t t);
38
39const mstring& SWeek(int lang,time_t t);
40const mstring& SMonth(int lang,time_t t);
41
42mstring httpTime(time_t t);
43mstring htcTime(int lang,time_t t);
44time_t htcTime(int lang,const sref& date);
45time_t cvtTime(const sref& code);
46
47int Language(const sref& s);
48
49#endif
diff --git a/src/mt/find_not_of.f b/src/mt/find_not_of.f
new file mode 100644
index 0000000..11d9287
--- /dev/null
+++ b/src/mt/find_not_of.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function find_not_of(s,n,c)
21 byte s(0:1),c(0:1)
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=0,m-1
25 if(c(s(i)).eq.0)go to 100
26 10 continue
27 do 20 i=m,n-1,16
28 if(c(s(i)).eq.0)go to 100
29 if(c(s(i+1)).eq.0)go to 101
30 if(c(s(i+2)).eq.0)go to 102
31 if(c(s(i+3)).eq.0)go to 103
32 if(c(s(i+4)).eq.0)go to 104
33 if(c(s(i+5)).eq.0)go to 105
34 if(c(s(i+6)).eq.0)go to 106
35 if(c(s(i+7)).eq.0)go to 107
36 if(c(s(i+8)).eq.0)go to 108
37 if(c(s(i+9)).eq.0)go to 109
38 if(c(s(i+10)).eq.0)go to 110
39 if(c(s(i+11)).eq.0)go to 111
40 if(c(s(i+12)).eq.0)go to 112
41 if(c(s(i+13)).eq.0)go to 113
42 if(c(s(i+14)).eq.0)go to 114
43 if(c(s(i+15)).eq.0)go to 115
44 20 continue
45 find_not_of=-1
46 return
47 100 find_not_of=i
48 return
49 101 find_not_of=i+1
50 return
51 102 find_not_of=i+2
52 return
53 103 find_not_of=i+3
54 return
55 104 find_not_of=i+4
56 return
57 105 find_not_of=i+5
58 return
59 106 find_not_of=i+6
60 return
61 107 find_not_of=i+7
62 return
63 108 find_not_of=i+8
64 return
65 109 find_not_of=i+9
66 return
67 110 find_not_of=i+10
68 return
69 111 find_not_of=i+11
70 return
71 112 find_not_of=i+12
72 return
73 113 find_not_of=i+13
74 return
75 114 find_not_of=i+14
76 return
77 115 find_not_of=i+15
78 return
79 end
80
diff --git a/src/mt/find_of.f b/src/mt/find_of.f
new file mode 100644
index 0000000..81cd99d
--- /dev/null
+++ b/src/mt/find_of.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function find_of(s,n,c)
21 byte s(0:1),c(0:1)
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=0,m-1
25 if(c(s(i)).ne.0)go to 100
26 10 continue
27 do 20 i=m,n-1,16
28 if(c(s(i)).ne.0)go to 100
29 if(c(s(i+1)).ne.0)go to 101
30 if(c(s(i+2)).ne.0)go to 102
31 if(c(s(i+3)).ne.0)go to 103
32 if(c(s(i+4)).ne.0)go to 104
33 if(c(s(i+5)).ne.0)go to 105
34 if(c(s(i+6)).ne.0)go to 106
35 if(c(s(i+7)).ne.0)go to 107
36 if(c(s(i+8)).ne.0)go to 108
37 if(c(s(i+9)).ne.0)go to 109
38 if(c(s(i+10)).ne.0)go to 110
39 if(c(s(i+11)).ne.0)go to 111
40 if(c(s(i+12)).ne.0)go to 112
41 if(c(s(i+13)).ne.0)go to 113
42 if(c(s(i+14)).ne.0)go to 114
43 if(c(s(i+15)).ne.0)go to 115
44 20 continue
45 find_of=-1
46 return
47 100 find_of=i
48 return
49 101 find_of=i+1
50 return
51 102 find_of=i+2
52 return
53 103 find_of=i+3
54 return
55 104 find_of=i+4
56 return
57 105 find_of=i+5
58 return
59 106 find_of=i+6
60 return
61 107 find_of=i+7
62 return
63 108 find_of=i+8
64 return
65 109 find_of=i+9
66 return
67 110 find_of=i+10
68 return
69 111 find_of=i+11
70 return
71 112 find_of=i+12
72 return
73 113 find_of=i+13
74 return
75 114 find_of=i+14
76 return
77 115 find_of=i+15
78 return
79 end
80
diff --git a/src/mt/issue.cc b/src/mt/issue.cc
new file mode 100644
index 0000000..fa31f36
--- /dev/null
+++ b/src/mt/issue.cc
@@ -0,0 +1,51 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/issue.h>
21#include <signal.h>
22#include <sys/wait.h>
23
24void issue_t::run(mstream& out,const sref& in) throw(merror_t)
25{
26 int ip[2],op[2];
27 pipe(ip); pipe(op);
28 sigignore(SIGPIPE);
29 int pid=fork();
30 if(pid) {
31 close(ip[0]);
32 close(op[1]);
33 write(ip[1],in.data(),in.size());
34 close(ip[1]);
35 sref_t buf; int n;
36 while((n=read(op[0],buf,sizeof(sref_t)))>0) out.write(buf,n);
37 close(op[0]);
38 if(wait(0)<0) kill(pid,SIGKILL);
39 }
40 else {
41 close(ip[1]);
42 close(op[0]);
43 dup2(ip[0],0);
44 close(ip[0]);
45 dup2(op[1],1);
46 close(op[1]);
47 execv(*argv(),argv());
48 _exit(0);
49 }
50}
51
diff --git a/src/mt/issue.h b/src/mt/issue.h
new file mode 100644
index 0000000..27f6aa0
--- /dev/null
+++ b/src/mt/issue.h
@@ -0,0 +1,55 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef ISSUEH
21#define ISSUEH
22
23#include <mt/mstring.h>
24#include <mt/mvec.h>
25#include <mt/split.h>
26
27// ISSUE A PIPED COMMAND
28//
29// This class is tuned to work in a mt environment.
30// The aim is to make this work locally as if it was
31// a single thread returning something to the stream out
32// depending on the input in.
33
34struct issue_t {
35 mrvec<char*> arg;
36
37 issue_t() {}
38 ~issue_t() { clear(); }
39
40 issue_t(const sref& s,const charset& ws=cset_ws) {
41 sref first,rest=s;
42 while(Split(first,rest,ws)) arg.push_back(first.news());
43 arg.push_back(0);
44 }
45
46 void clear() { for(int i=0;i<arg.size();i++) delete arg[i]; arg.clear(); }
47 void add(const sref& s) { arg.push_back(s.news()); }
48 void end() { arg.push_back(0); }
49 char* const* argv() const { return arg.begin(); }
50
51 void run(mstream& out,const sref& in) throw(merror_t);
52};
53
54#endif
55
diff --git a/src/mt/lock.cc b/src/mt/lock.cc
new file mode 100644
index 0000000..5b72967
--- /dev/null
+++ b/src/mt/lock.cc
@@ -0,0 +1,114 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/lock.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <sys/utsname.h>
25#include <signal.h>
26using namespace std;
27
28const mstring LOCK=".lock";
29
30void LockFile(const mstring& path,int prot) throw(merror_t)
31{
32 mstring name=path+LOCK; int fd;
33 while((fd=open(name.c_str(),O_CREAT|O_WRONLY|O_TRUNC|O_EXCL,prot))==-1&&
34 errno==EEXIST) sleep(1);
35 if(fd<0) THROW("lock: could not create lock file "<<name);
36 close(fd);
37}
38
39int remove(const char* path);
40void UnlockFile(const mstring& path)
41{
42 remove((path+LOCK).c_str());
43}
44
45///////////////////////////////////////////////////////////////////
46
47proclock_t::proclock_t(const mstring& p,int prot) : pid(0),path(p+LOCK)
48{
49 mstring buf,name=path;
50 int fd=open(path.c_str(),O_CREAT|O_WRONLY|O_TRUNC|O_EXCL,prot);
51 if(fd<0) {
52 if(errno==EEXIST) {
53 buf.load(path);
54 int oldpid=atoi(buf);
55 if(kill(oldpid,0)==0) THROW("proclock: already running as "<<buf)
56 else fd=open(path.c_str(),O_CREAT|O_WRONLY|O_TRUNC,prot);
57 }
58 else THROW("proclock: could not create lock file "<<path);
59 }
60 pid=getpid();
61 buf.convert("%d",pid);
62 write(fd,buf.data(),buf.size());
63 close(fd);
64}
65
66proclock_t::~proclock_t()
67{
68 if(getpid()==pid) remove(path.c_str());
69}
70
71///////////////////////////////////////////////////////////////////
72
73nodelock_t::nodelock_t(const mstring& p,int prot) : pid(0),path(p+LOCK)
74{
75 struct utsname uts; uname(&uts);
76 mstring buf;
77 int fd=open(path.c_str(),O_CREAT|O_WRONLY|O_TRUNC|O_EXCL,prot);
78 if(fd<0) {
79 if(errno==EEXIST) {
80 if(buf.load(path)>=0) {
81 if(buf.nempty()&&buf!=sref(uts.nodename))
82 THROW("nodelock: already locked on "<<buf);
83 }
84 else {
85 fd=open(path.c_str(),O_CREAT|O_WRONLY|O_TRUNC,prot);
86 pid=getpid();
87 buf=uts.nodename;
88 write(fd,buf.data(),buf.size());
89 close(fd);
90 }
91 }
92 else THROW("nodelock: could not create lock file "<<path);
93 }
94 else {
95 pid=getpid();
96 buf=uts.nodename;
97 write(fd,buf.data(),buf.size());
98 close(fd);
99 }
100}
101
102nodelock_t::~nodelock_t()
103{
104 if(getpid()==pid) remove(path.c_str());
105}
106
107///////////////////////////////////////////////////////////////////
108
109void ProcTerminate(const mstring& p,int stime)
110{
111 mstring buf,path=p+LOCK;
112 if(buf.load(path)>=0) while(!kill(atoi(buf),SIGTERM)) sleep(stime);
113}
114
diff --git a/src/mt/lock.h b/src/mt/lock.h
new file mode 100644
index 0000000..e019158
--- /dev/null
+++ b/src/mt/lock.h
@@ -0,0 +1,72 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef LOCKH
21#define LOCKH
22
23#include <mt/mstring.h>
24
25// OFFERS TWO LOCKING MECHANISMS
26
27void LockFile(const mstring& path,int prot=0660) throw(merror_t);
28void UnlockFile(const mstring& path);
29
30// These functions create an exclusive lock on path by
31// creating a file path.lock.
32// Works well and is the same mechnism used by
33// mailing systems.
34
35////////////////////////////////////////////
36
37struct proclock_t {
38 pid_t pid;
39 mstring path;
40 proclock_t(const mstring& p,int prot=0660);
41 ~proclock_t();
42};
43
44#define PROCLOCK(p) proclock_t proclock(p)
45
46// The proclock class creates a file named path.lock
47// and stores the curent process id in it.
48// once the destructor is called in the same
49// process, the file is removed.
50
51////////////////////////////////////////////
52
53struct nodelock_t {
54 pid_t pid;
55 mstring path;
56 nodelock_t(const mstring& p,int prot=0660);
57 ~nodelock_t();
58};
59
60#define NODELOCK(p) nodelock_t nodelock(p)
61
62// The nodelock class creates a file named path.lock
63// and stores the curent network node name in it.
64// once the destructor is called in the same
65// process, the file is removed.
66
67////////////////////////////////////////////
68
69void ProcTerminate(const mstring& path,int stime=2);
70
71#endif
72
diff --git a/src/mt/lookup.cc b/src/mt/lookup.cc
new file mode 100644
index 0000000..c0e72c8
--- /dev/null
+++ b/src/mt/lookup.cc
@@ -0,0 +1,88 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/lookup.h>
21#include <mt/mvec.h>
22#include <mt/lock.h>
23#include <arpa/inet.h>
24#include <netinet/in.h>
25#include <sys/socket.h>
26
27const time_t VALIDSEC=120;
28static msvec<IPnode> cache;
29static mutex_t mutex;
30
31int Lookup(IPnode& node,const in_addr& ia)
32{
33 MLOCK(mutex);
34 IPnode* p=cache.begin();
35 time_t now=time(0);
36 while(p<cache.end()) {
37 if(now>p->valid) cache.erase(p);
38 else if(memcmp(&p->addr,&ia,sizeof(ia))==0) {p->valid=now+VALIDSEC;node=*p;return 1;}
39 else p++;
40 }
41 hostent hent;
42 sref_t buf;
43 int herr;
44 hostent* hp=0;
45 gethostbyaddr_r((const char*)&ia,sizeof(ia),AF_INET,
46 &hent,
47 buf,sizeof(sref_t),
48 &hp,
49 &herr);
50 if(!hp) return 0;
51 memcpy(&node.addr,hp->h_addr,sizeof(hp->h_length));
52 node.ip=inet_ntoa(node.addr);
53 node.name=hp->h_name;
54 node.valid=now+VALIDSEC;
55 cache.push_back(node);
56 return 1;
57}
58
59int Lookup(IPnode& node,const sref& s)
60{
61 MLOCK(mutex);
62 IPnode* p=cache.begin();
63 time_t now=time(0);
64 while(p<cache.end()) {
65 if(now>p->valid) cache.erase(p);
66 else if(p->ip==s||p->name==s) { p->valid=now+VALIDSEC; node=*p; return 1; }
67 else p++;
68 }
69 hostent hent;
70 sref_t sbuf,buf;
71 int herr;
72 hostent* hp=0;
73 for(int i=0;s[i];i++) if(s[i]!='.'&&(s[i]<'0'||s[i]>'9')) {
74 gethostbyname_r(s.copyto(sbuf),&hent,buf,sizeof(sref_t),&hp,&herr);
75 break;
76 }
77 if(!hp) {
78 unsigned long a=inet_addr(s.copyto(buf));
79 gethostbyaddr_r((char*)&a,sizeof(a),AF_INET,&hent,buf,sizeof(sref_t),&hp,&herr);
80 }
81 if(!hp) return 0;
82 memcpy(&node.addr,hp->h_addr,sizeof(hp->h_length));
83 node.ip=inet_ntoa(node.addr);
84 node.name=hp->h_name;
85 node.valid=now+VALIDSEC;
86 cache.push_back(node);
87 return 1;
88}
diff --git a/src/mt/lookup.h b/src/mt/lookup.h
new file mode 100644
index 0000000..d073766
--- /dev/null
+++ b/src/mt/lookup.h
@@ -0,0 +1,32 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef LOOKUPH
21#define LOOKUPH
22
23#include <mt/mstring.h>
24#include <netdb.h>
25#include <netinet/in.h>
26
27struct IPnode { time_t valid; in_addr addr; mstring ip,name; };
28
29int Lookup(IPnode& node,const sref& s);
30int Lookup(IPnode& node,const in_addr& ia);
31
32#endif
diff --git a/src/mt/mlock.h b/src/mt/mlock.h
new file mode 100644
index 0000000..4639cf4
--- /dev/null
+++ b/src/mt/mlock.h
@@ -0,0 +1,48 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MLOCKH
21#define MLOCKH
22
23#if 1
24#include <pthread.h>
25typedef pthread_mutex_t mutex_t;
26typedef pthread_cond_t mtcond_t;
27const mutex_t MUTEX_INIT=PTHREAD_MUTEX_INITIALIZER;
28const mtcond_t MTCOND_INIT=PTHREAD_COND_INITIALIZER;
29struct mlock_t {
30 mutex_t* lock;
31
32 mlock_t(mutex_t& m) { pthread_mutex_lock(lock=&m); }
33 ~mlock_t() { if(lock) pthread_mutex_unlock(lock); }
34};
35#define MLOCK(m) mlock_t mlock(m)
36#define MSUSPEND(m,c) { MLOCK(m); pthread_cond_wait(&c,&m); }
37#define MCONTINUE(c) pthread_cond_signal(&c)
38#else
39typedef int mutex_t;
40typedef int mtcond_t;
41const mutex_t MUTEX_INIT=0;
42const mtcond_t MTCOND_INIT=0;
43#define MLOCK(m)
44#define MSUSPEND(m,c)
45#define MCONTINUE(c)
46#endif
47
48#endif
diff --git a/src/mt/mread.cc b/src/mt/mread.cc
new file mode 100644
index 0000000..da5a966
--- /dev/null
+++ b/src/mt/mread.cc
@@ -0,0 +1,135 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mread.h>
21#include <mt/split.h>
22#include <poll.h>
23#include <signal.h>
24#include <errno.h>
25
26const int MSEC=4000;
27const int RETRY=3;
28const int TIMEOUT=2;
29
30//////////////////////////////////////////////////////////////////////////
31
32mread::mread() : fd(-1),buf()
33{
34}
35
36mread::mread(int f) : fd(f),buf()
37{
38}
39
40//////////////////////////////////////////////////////////////////////////
41
42void mread::clear()
43{
44 buf.clear();
45}
46
47int mread::poll()
48{
49 pollfd pfd={fd,POLLIN,0};
50 return ::poll(&pfd,1,MSEC);
51}
52
53int mread::read(char* s,int n)
54{
55 if(buf.empty()) {
56 int m=::read(fd,s,n);
57 for(int i=0;i<RETRY&&m<0&&errno==EAGAIN&&poll()>=0;i++) m=::read(fd,s,n);
58 if(m<0&&n) *s=0;
59 return m;
60 }
61 else {
62 if(n>buf.size()) n=buf.size();
63 memcpy(s,buf.data(),n);
64 buf.erase(0,n);
65 return n;
66 }
67}
68
69void mread::putback(const sref& s)
70{
71 if(s.nempty()) buf.insert(0,s);
72}
73
74//////////////////////////////////////////////////////////////////////////
75
76int mread::readx(char* s,int n)
77{
78 int tries=0,acc=0;
79 while(acc<n) {
80 int m=read(s+acc,n-acc);
81 if(m<0) return -1;
82 else if(m==0) {
83 if(poll()<0) return -1;
84 if(tries++>=TIMEOUT) return acc;
85 }
86 else {
87 acc+=m;
88 tries=0;
89 }
90 }
91 return acc;
92}
93
94//////////////////////////////////////////////////////////////////////////
95
96int mread::readln(char* s,int n)
97{
98 int tries=0,acc=0;
99 while(acc<n) {
100 int m=read(s+acc,n-acc);
101 if(m<0) return -1;
102 else if(m==0) {
103 if(poll()<0) return -1;
104 if(tries++>=TIMEOUT) return acc?-1:0;
105 }
106 else {
107 int p=sref(s+acc,m).find('\n')+1;
108 if(p>0) { acc+=p; putback(sref(s+acc,m-p)); return acc; }
109 else { acc+=m; tries=0; }
110 }
111 }
112 return acc;
113}
114
115int mread::readpara(char* s,int n)
116{
117 int tries=0,acc=0;
118 while(acc<n) {
119 int m=read(s+acc,n-acc);
120 if(m<0) return -1;
121 else if(m==0) {
122 if(poll()<0) return -1;
123 if(tries++>=TIMEOUT) return acc?-1:0;
124 }
125 else {
126 int found=0;
127 sref first,rest(s+acc,m);
128 while(Splitln(first,rest)) if(first.empty()) { found=1; break; }
129 if(found) { acc=rest.begin()-s; putback(rest); return acc; }
130 else { acc+=m; tries=0; }
131 }
132 }
133 return acc;
134}
135
diff --git a/src/mt/mread.h b/src/mt/mread.h
new file mode 100644
index 0000000..11516a2
--- /dev/null
+++ b/src/mt/mread.h
@@ -0,0 +1,63 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MREADH
21#define MREADH
22
23// These functions work with nonblocking pipes
24// as well as normal devices, and does not produce
25// any signals on pipe errors
26
27#include <mt/mstring.h>
28#include <unistd.h>
29#include <fcntl.h>
30
31class mread {
32public:
33 mread();
34 mread(int f);
35
36 void setfd(int f) { clear(); fd=f; }
37 int getfd() const { return fd; }
38
39 void setflag(int f) { fcntl(fd,F_SETFL,f); }
40 int getflag() const { return fcntl(fd,F_GETFL,0); }
41
42 // Basic, pipe-safe, normally non-blocking, reads
43 void clear();
44 int poll();
45 int read(char* s,int n);
46 void putback(const sref& s);
47
48 // Buffered reads
49 int readx(char* s,int n); // may timeout and return less than wanted
50 int readln(char* s,int n);
51 int readpara(char* s,int n);
52
53private:
54 int fd;
55 mstring buf;
56};
57
58// All functions return number of bytes written, or -1 on error.
59// Note that although ln and para continues to read until
60// it finds a newline or a paragraph, it may read more than that.
61// Use clear() to restore reading state
62
63#endif
diff --git a/src/mt/mset.cc b/src/mt/mset.cc
new file mode 100644
index 0000000..ec5b69e
--- /dev/null
+++ b/src/mt/mset.cc
@@ -0,0 +1,81 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mset.h>
21#include <algorithm>
22using namespace std;
23
24mset::mset() : rpile() {}
25mset::mset(const sref& in) : rpile() {
26 sref first,rest=in;
27 while(Split(first,rest)) insert(first);
28}
29
30/////////////////////////////////////////////////////////////////////////////
31
32int mset::exist(const sref& t) const {
33 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),t);
34 return p.first!=p.second;
35}
36int mset::insert(const sref& t) {
37 pair<iterator,iterator> p=equal_range(begin(),end(),t);
38 if(p.first==p.second) { rpile::insert(p.second,t); return 1; }
39 else return 0;
40}
41
42/////////////////////////////////////////////////////////////////////////////
43
44void mset::Union(const mset& a,const mset& b) {
45 clear();
46 for(int i=0;i<a.size();i++) insert(a[i]);
47 for(int i=0;i<b.size();i++) insert(b[i]);
48}
49void mset::Intersection(const mset& a,const mset& b) {
50 clear();
51 for(int i=0;i<a.size();i++) if(b.exist(a[i])) insert(a[i]);
52}
53void mset::Difference(const mset& a,const mset& b) {
54 clear();
55 for(int i=0;i<a.size();i++) if(!b.exist(a[i])) insert(a[i]);
56}
57
58/////////////////////////////////////////////////////////////////////////////
59
60mstream& operator<<(mstream& out,const mset& m) {
61 for(int i=0;i<m.size();i++) { if(i) out.put(' '); out<<m[i]; } return out;
62}
63
64/////////////////////////////////////////////////////////////////////////////
65
66int msset::exist(const mstring& t) const {
67 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),t);
68 return p.first!=p.second;
69}
70int msset::insert(const mstring& t) {
71 pair<iterator,iterator> p=equal_range(begin(),end(),t);
72 if(p.first==p.second) { spile::insert(p.second,t); return 1; }
73 else return 0;
74}
75
76/////////////////////////////////////////////////////////////////////////////
77
78mstream& operator<<(mstream& out,const msset& m) {
79 for(int i=0;i<m.size();i++) { if(i) out.put(' '); out<<m[i]; } return out;
80}
81
diff --git a/src/mt/mset.h b/src/mt/mset.h
new file mode 100644
index 0000000..469166f
--- /dev/null
+++ b/src/mt/mset.h
@@ -0,0 +1,62 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MSETH
21#define MSETH
22
23#include <mt/split.h>
24#include <mt/mstring.h>
25#include <mt/mvec.h>
26
27typedef mrvec<sref> rpile;
28
29struct mset : public rpile
30{
31 typedef rpile::iterator iterator;
32 typedef rpile::const_iterator const_iterator;
33
34 mset();
35 mset(const sref& in);
36
37 int exist(const sref& t) const;
38 int insert(const sref& t);
39
40 void Union(const mset& a,const mset& b);
41 void Intersection(const mset& a,const mset& b);
42 void Difference(const mset& a,const mset& b);
43};
44
45mstream& operator<<(mstream& out,const mset& m);
46
47//////////////////////////////////////////////////////////
48
49typedef msvec<mstring> spile;
50
51struct msset : public spile
52{
53 typedef spile::iterator iterator;
54 typedef spile::const_iterator const_iterator;
55
56 int exist(const mstring& t) const;
57 int insert(const mstring& t);
58};
59
60mstream& operator<<(mstream& out,const mset& m);
61
62#endif
diff --git a/src/mt/msmap.cc b/src/mt/msmap.cc
new file mode 100644
index 0000000..c1284fb
--- /dev/null
+++ b/src/mt/msmap.cc
@@ -0,0 +1,84 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/msmap.h>
21#include <algorithm>
22using namespace std;
23
24const sref* rrmap::get(const sref& t) const
25{
26 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),rrstring(t));
27 return p.first!=p.second?&p.first->second:0;
28}
29
30const sref* rrmap::add(const sref& t,const sref& s)
31{
32 rrstring tmp(t,s);
33 pair<iterator,iterator> p=equal_range(begin(),end(),tmp);
34 if(p.first!=p.second) return &(*p.first=tmp).second;
35 else return &insert(p.second,tmp)->second;
36}
37
38void rrmap::sort()
39{
40 ::sort(begin(),end());
41}
42
43////////////////////////////////////////////////////////////////
44
45int rimap::get(const sref& t) const
46{
47 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),rimap_t(t));
48 return p.first!=p.second?p.first->at:-1;
49}
50
51int rimap::add(const sref& t,int at)
52{
53 rimap_t tmp(t,at);
54 pair<iterator,iterator> p=equal_range(begin(),end(),tmp);
55 if(p.first!=p.second) return (*p.first=tmp).at;
56 else return insert(p.second,tmp)->at;
57}
58
59void rimap::sort()
60{
61 ::sort(begin(),end());
62}
63
64////////////////////////////////////////////////////////////////
65
66const mstring* ssmap::get(const mstring& t) const
67{
68 pair<const_iterator,const_iterator> p=equal_range(begin(),end(),sstring(t));
69 return p.first!=p.second?&p.first->second:0;
70}
71
72const mstring* ssmap::add(const mstring& t,const mstring& s)
73{
74 sstring tmp(t,s);
75 pair<iterator,iterator> p=equal_range(begin(),end(),tmp);
76 if(p.first!=p.second) return &(*p.first=tmp).second;
77 else return &insert(p.second,tmp)->second;
78}
79
80void ssmap::sort()
81{
82 ::sort(begin(),end());
83}
84
diff --git a/src/mt/msmap.h b/src/mt/msmap.h
new file mode 100644
index 0000000..a719a7b
--- /dev/null
+++ b/src/mt/msmap.h
@@ -0,0 +1,89 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MSMAPH
21#define MSMAPH
22
23#include <mt/mstring.h>
24#include <mt/mvec.h>
25
26struct rrstring {
27 sref first,second;
28 rrstring() : first(),second() {}
29 explicit rrstring(const sref& a) : first(a),second() {}
30 rrstring(const sref& a,const sref& b) : first(a),second(b) {}
31};
32inline bool operator<(const rrstring& a,const rrstring& b) { return a.first<b.first; }
33
34typedef mrvec<rrstring> rrpile;
35
36struct rrmap : public rrpile
37{
38 typedef rrpile::iterator iterator;
39 typedef rrpile::const_iterator const_iterator;
40
41 const sref* get(const sref& t) const;
42 const sref* add(const sref& t,const sref& s);
43 void sort();
44};
45
46//////////////////////////////////////////////////////////////////
47
48struct rimap_t {
49 sref name;
50 int at;
51 rimap_t() : name(),at(0) {}
52 explicit rimap_t(const sref& a) : name(a),at(0) {}
53 rimap_t(const sref& a,int p) : name(a),at(p) {}
54};
55inline bool operator<(const rimap_t& a,const rimap_t& b) { return a.name<b.name; }
56
57struct rimap : public mrvec<rimap_t>
58{
59 typedef mrvec<rimap_t>::iterator iterator;
60 typedef mrvec<rimap_t>::const_iterator const_iterator;
61
62 int get(const sref& t) const;
63 int add(const sref& t,int at);
64 void sort();
65};
66
67//////////////////////////////////////////////////////////////////
68
69struct sstring {
70 mstring first,second;
71 sstring() : first(),second() {}
72 explicit sstring(const mstring& a) : first(a),second() {}
73 sstring(const mstring& a,const mstring& b) : first(a),second(b) {}
74};
75inline bool operator<(const sstring& a,const sstring& b) { return a.first<b.first; }
76
77typedef msvec<sstring> sspile;
78
79struct ssmap : public sspile
80{
81 typedef sspile::iterator iterator;
82 typedef sspile::const_iterator const_iterator;
83
84 const mstring* get(const mstring& t) const;
85 const mstring* add(const mstring& t,const mstring& s);
86 void sort();
87};
88
89#endif
diff --git a/src/mt/mstream.cc b/src/mt/mstream.cc
new file mode 100644
index 0000000..3d94936
--- /dev/null
+++ b/src/mt/mstream.cc
@@ -0,0 +1,72 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mstream.h>
21#include <poll.h>
22#include <signal.h>
23
24const char cvt_form_f[]="%#.12f";
25const int MSEC=4000;
26
27sref ftoa(sref_t& buf,double f)
28{
29 char* e=buf+sprintf(buf,cvt_form_f,f)-1;
30 while(*e=='0') e--; if(*e=='.') e--;
31 return sref(buf,e-buf+1);
32}
33
34///////////////////////////////////////////////////////////
35
36int mstream::appc(char c) { return -1; }
37int mstream::appi(int i) { return -1; }
38int mstream::appf(double f) { return -1; }
39int mstream::apps(const sref& s) { return -1; }
40
41///////////////////////////////////////////////////////////
42
43int cvt_stream::appi(int i) { sref_t buf; return apps(itoa(buf,i)); }
44int cvt_stream::appf(double f) { sref_t buf; return apps(ftoa(buf,f)); }
45
46///////////////////////////////////////////////////////////
47
48int fp_stream::appc(char c) { return putc(c,fp)<0?-1:1; }
49int fp_stream::apps(const sref& s) { return fwrite(s.data(),s.size(),1,fp); }
50
51///////////////////////////////////////////////////////////
52
53int fd_stream::appc(char c) { return ::write(fd,&c,1); }
54int fd_stream::apps(const sref& s) { return ::write(fd,s.data(),s.size()); }
55
56///////////////////////////////////////////////////////////
57
58int pipe_stream::appc(char c) { return mwrite(&c,1); }
59int pipe_stream::apps(const sref& s) { return mwrite(s.data(),s.size()); }
60
61int pipe_stream::mwrite(const char* s,int n)
62{
63 int old=n;
64 while(n>0&&!hup) {
65 pollfd pfd={fd,POLLOUT,0};
66 if(::poll(&pfd,1,MSEC)<0) return hup=-1;
67 int m=::write(fd,s,n);
68 if(m<0) return hup=-1;
69 s+=m; n-=m;
70 }
71 return hup?-1:old;
72}
diff --git a/src/mt/mstream.h b/src/mt/mstream.h
new file mode 100644
index 0000000..4f5aeaf
--- /dev/null
+++ b/src/mt/mstream.h
@@ -0,0 +1,103 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MSTREAMH
21#define MSTREAMH
22
23#include <mt/stringref.h>
24#include <unistd.h>
25#include <stdio.h>
26
27///////////////////////////////////////////////////////////
28
29const char cvt_form_i[]="%d";
30
31///////////////////////////////////////////////////////////
32
33inline sref itoa(sref_t& buf,int i) { return sref(buf,sprintf(buf,cvt_form_i,i)); }
34sref ftoa(sref_t& buf,double f);
35
36///////////////////////////////////////////////////////////
37
38struct mstream {
39 virtual int appc(char c);
40 virtual int appi(int i);
41 virtual int appf(double f);
42 virtual int apps(const sref& s);
43
44 mstream& put(char c) { return appc(c),*this; }
45 int write(const char* s,int n) { return apps(sref(s,n)); }
46};
47
48inline mstream& operator<<(mstream& out,int i) { return out.appi(i),out; }
49inline mstream& operator<<(mstream& out,long l) { return out.appi(l),out; }
50inline mstream& operator<<(mstream& out,unsigned u) { return out.appi(u),out; }
51inline mstream& operator<<(mstream& out,unsigned long ul) { return out.appi(ul),out; }
52inline mstream& operator<<(mstream& out,double f) { return out.appf(f),out; }
53
54inline mstream& operator<<(mstream& out,const sref& s) { return out.apps(s),out; }
55inline mstream& operator<<(mstream& out,const char* s) { return out.apps(sref(s)),out; }
56
57///////////////////////////////////////////////////////////
58
59struct cvt_stream : public mstream {
60 int appi(int i);
61 int appf(double f);
62};
63
64///////////////////////////////////////////////////////////
65
66struct fp_stream : public cvt_stream {
67 FILE* fp;
68
69 int appc(char c);
70 int apps(const sref& s);
71
72 fp_stream(FILE* f) : fp(f) {}
73
74 int flush() { return fflush(fp); }
75};
76
77///////////////////////////////////////////////////////////
78
79struct fd_stream : public cvt_stream {
80 int fd;
81
82 int appc(char c);
83 int apps(const sref& s);
84
85 fd_stream(int f) : fd(f) {}
86};
87
88///////////////////////////////////////////////////////////
89
90struct pipe_stream : public cvt_stream {
91 int fd,hup;
92
93 int appc(char c);
94 int apps(const sref& s);
95
96 pipe_stream(int f) : fd(f),hup(0) {}
97
98 int mwrite(const char* s,int n);
99};
100
101///////////////////////////////////////////////////////////
102
103#endif
diff --git a/src/mt/mstring.cc b/src/mt/mstring.cc
new file mode 100644
index 0000000..7be82e3
--- /dev/null
+++ b/src/mt/mstring.cc
@@ -0,0 +1,139 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mstring.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <stdarg.h>
25
26uniheap<ms_mincaps> mstring::heap;
27
28///////////////////////////////////////////////////////////////////
29
30mstring::mstring() : sref(heap.push(),0),caps(ms_mincaps) {
31 map[dim]=0;
32}
33mstring::mstring(int n) : sref(heap.push(),0),caps(ms_mincaps) {
34 if(caps<n) { while(caps<n) caps<<=1; heap.pop(map); map=(char*)malloc(caps); }
35 map[dim=0]=0;
36}
37mstring::mstring(int n,char c) : sref(heap.push(),0),caps(ms_mincaps) {
38 resize(n);
39 memset(map,c,dim);
40}
41mstring::mstring(const char* s) : sref(heap.push(),0),caps(ms_mincaps) {
42 resize(strlen(s));
43 memcpy(map,s,dim);
44}
45mstring::mstring(const char* s,int n) : sref(heap.push(),0),caps(ms_mincaps) {
46 resize(n);
47 memcpy(map,s,dim);
48}
49mstring::mstring(const sref& s) : sref(heap.push(),0),caps(ms_mincaps) {
50 resize(s.size());
51 memcpy(map,s.data(),dim);
52}
53mstring::mstring(const mstring& s) : sref(heap.push(),0),caps(ms_mincaps) {
54 resize(s.dim);
55 memcpy(map,s.map,dim);
56}
57mstring::~mstring() {
58 if(caps==ms_mincaps) heap.pop(map);
59 else free(map);
60}
61
62///////////////////////////////////////////////////////////////////
63
64void mstring::erase(int pos,int n)
65{
66 if(pos<0) { pos+=dim; if(pos<0) pos=0; }
67 if(pos<dim) {
68 if(n<0) { n+=dim+1; if(n<0) n=0; }
69 if(n>=dim-pos) map[dim=pos]=0;
70 else { memmove(map+pos,map+pos+n,dim-pos-n); map[dim-=n]=0; }
71 }
72}
73
74void mstring::reserve(int n) {
75 if(caps<=n) {
76 if(caps==ms_mincaps) {
77 while(caps<=n) caps<<=1;
78 char* p=(char*)memcpy(malloc(caps),map,dim);
79 heap.pop(map);
80 map=p;
81 }
82 else {
83 while(caps<=n) caps<<=1;
84 map=(char*)realloc(map,caps);
85 }
86 }
87}
88
89///////////////////////////////////////////////////////////////////
90
91int mstring::load(const mstring& path)
92{
93 int fd=open(path.c_str(),O_RDONLY);
94 if(fd<0) return -1;
95 struct stat fs; fstat(fd,&fs);
96 resize(fs.st_size);
97 read(fd,map,dim);
98 close(fd);
99 return dim;
100}
101
102///////////////////////////////////////////////////////////////////
103
104mstring& mstring::convert(const char* format,...)
105{
106 sref_t buf;
107 va_list ap;
108 va_start(ap,format);
109 resize(vsprintf(buf,format,ap));
110 memcpy(map,buf,dim);
111 va_end(ap);
112 return *this;
113}
114
115///////////////////////////////////////////////////////////////////
116
117int swrite::appc(char c) { return mp->put(c),1; }
118int swrite::apps(const sref& s) { return mp->put(s),s.size(); }
119
120///////////////////////////////////////////////////////////////////
121
122int mswrite::appc(char c) { return m.put(c),1; }
123int mswrite::apps(const sref& s) { return m.put(s),s.size(); }
124
125///////////////////////////////////////////////////////////////////
126
127int merror_t::appc(char c) { return desc.put(c),1; }
128int merror_t::apps(const sref& s) { return desc.put(s),s.size(); }
129
130///////////////////////////////////////////////////////////////////
131
132void getline(mstring& m,FILE* fp,char end)
133{
134 m.clear();
135 int c=getc(fp);
136 while(c!=end&&c!=EOF) { m.append(1,c); c=getc(fp); }
137}
138
139
diff --git a/src/mt/mstring.h b/src/mt/mstring.h
new file mode 100644
index 0000000..be07c1a
--- /dev/null
+++ b/src/mt/mstring.h
@@ -0,0 +1,222 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MSTRINGH
21#define MSTRINGH
22
23#include <mt/mstream.h>
24#include <mt/uniheap.h>
25
26const int ms_mincaps=32;
27
28class mstring : public sref {
29public:
30 mstring();
31 explicit mstring(int n);
32 mstring(int n,char c);
33 mstring(const char* s);
34 mstring(const char* s,int n);
35 mstring(const sref& s);
36 mstring(const mstring& s);
37 ~mstring();
38
39 ////////////////////////////////////////////////////////////////
40
41 const char* c_str() const { return map; }
42 int capacity() const { return caps; }
43
44 void clear() { map[dim=0]=0; }
45
46 int own(const sref& s) const { int p=s.data()-map; return p>=0&&p<caps; }
47
48 ////////////////////////////////////////////////////////////////
49
50 void assign(int sdim,char c) {
51 resize(sdim);
52 memset(map,c,sdim);
53 }
54 void assign(const sref& s) {
55 reserve(s.size());
56 memmove(map,s.data(),s.size());
57 map[dim=s.size()]=0;
58 }
59
60 void put(char c) { if(dim+1>=caps) reserve(dim+1); map[dim++]=c; map[dim]=0; }
61 void put(const sref& s) {
62 reserve(dim+s.size());
63 memcpy(map+dim,s.data(),s.size());
64 map[dim+=s.size()]=0;
65 }
66
67 mstring& append(int sdim,char c) {
68 reserve(dim+sdim);
69 memset(map+dim,c,sdim);
70 map[dim+=sdim]=0;
71 return *this;
72 }
73
74 mstring& append(const sref& s) {
75 reserve(dim+s.size());
76 memmove(map+dim,s.data(),s.size());
77 map[dim+=s.size()]=0;
78 return *this;
79 }
80
81 int insert(int pos,int n) {
82 if(pos<0||pos>dim) return 0;
83 if(n) { reserve(dim+n); memmove(map+pos+n,map+pos,dim-pos); map[dim+=n]=0; }
84 return 1;
85 }
86
87 mstring& insert(int pos,int sdim,char c) {
88 if(insert(pos,sdim)) memset(map+pos,c,sdim);
89 return *this;
90 }
91 mstring& insert(int pos,const sref& s) {
92 if(insert(pos,s.size())) memcpy(map+pos,s.data(),s.size());
93 return *this;
94 }
95
96 mstring& replace(int pos,int n,int sdim,char c) {
97 if(insert(pos+n,sdim-n)) memset(map+pos,c,sdim);
98 return *this;
99 }
100 mstring& replace(int pos,int n,const sref& s) {
101 if(insert(pos+n,s.size()-n)) memcpy(map+pos,s.data(),s.size());
102 return *this;
103 }
104
105 ////////////////////////////////////////////////////////////////
106
107 void erase(int pos,int n=-1);
108 void reserve(int n);
109 void resize(int n) { reserve(n); map[dim=n]=0; }
110
111 ////////////////////////////////////////////////////////////////
112
113 mstring& operator=(const mstring& s) { assign(s); return *this; }
114 mstring& operator=(const sref& s) { assign(s); return *this; }
115 mstring& operator=(char c) { assign(1,c); return *this; }
116
117 mstring& operator+=(const sref& s) { return append(s); }
118 mstring& operator+=(char c) { return append(1,c); }
119
120 ////////////////////////////////////////////////////////////////
121
122 int load(const mstring& path);
123
124 ////////////////////////////////////////////////////////////////
125
126 // NOTE: if you apply convert to %s or any unbound data,
127 // you're in trouble. Internal buffer is sref_t.
128
129 mstring& convert(const char* format,...);
130
131protected:
132 static uniheap<ms_mincaps> heap;
133private:
134 int caps;
135};
136
137///////////////////////////////////////////////////////////////////
138
139inline void swap(mstring& a,mstring& b)
140{
141 char buf[sizeof(mstring)];
142 memcpy(buf,&a,sizeof(mstring));
143 memcpy(&a,&b,sizeof(mstring));
144 memcpy(&b,buf,sizeof(mstring));
145}
146
147///////////////////////////////////////////////////////////////////
148
149inline mstring operator+(const sref& a,const sref& b)
150{
151 return mstring(a).append(b);
152}
153inline mstring operator+(const sref& a,char b) {
154 return mstring(a).append(1,b);
155}
156inline mstring operator+(char a,const sref& b) {
157 return mstring(1,a).append(b);
158}
159
160///////////////////////////////////////////////////////////////////
161
162inline mstring btoa(int b) { return mstring(1,b?'1':'0'); }
163inline mstring itoa(int i) { sref_t buf; return mstring(itoa(buf,i)); }
164inline mstring ftoa(double f) { sref_t buf; return mstring(ftoa(buf,f)); }
165
166///////////////////////////////////////////////////////////////////
167
168const mstring ms_empty;
169
170///////////////////////////////////////////////////////////////////
171
172struct swrite : public cvt_stream {
173 mstring* mp;
174
175 int appc(char c);
176 int apps(const sref& s);
177
178 swrite() : mp(0) {}
179 swrite(mstring& m) : mp(&m) { mp->clear(); }
180
181 swrite& operator()(mstring& m) { (mp=&m)->clear(); return *this; }
182 swrite& hold(mstring& m) { mp=&m; return *this; }
183};
184
185///////////////////////////////////////////////////////////////////
186
187class mswrite : public cvt_stream {
188public:
189 mstring m;
190
191 int appc(char c);
192 int apps(const sref& s);
193
194 const mstring& str() const { return m; } // compatibility
195 void clear() { m.clear(); }
196
197 mswrite() : m() {}
198private:
199 mswrite(mstring&) {} // make no mistakes due to similarity with swrite
200};
201
202///////////////////////////////////////////////////////////////////
203
204struct merror_t : public cvt_stream {
205 int num;
206 mstring desc;
207
208 int appc(char c);
209 int apps(const sref& s);
210
211 merror_t(int n) : num(n),desc() {}
212};
213
214#define THROW(x) { merror_t merr(0); merr<<x; throw merr; }
215
216///////////////////////////////////////////////////////////////////
217
218void getline(mstring& m,FILE* fp,char end='\n');
219
220///////////////////////////////////////////////////////////////////
221
222#endif
diff --git a/src/mt/mvec.h b/src/mt/mvec.h
new file mode 100644
index 0000000..9f31c1e
--- /dev/null
+++ b/src/mt/mvec.h
@@ -0,0 +1,149 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MVECH
21#define MVECH
22
23#include <malloc.h>
24#include <string.h>
25#include <new>
26
27const int mv_mincaps=16;
28
29template <class T> class mrvec {
30public:
31 typedef T* iterator;
32 typedef const T* const_iterator;
33
34 mrvec():
35 map((T*)malloc(mv_mincaps*sizeof(T))),dim(0),caps(mv_mincaps) {}
36 mrvec(int n):
37 map((T*)malloc(mv_mincaps*sizeof(T))),dim(0),caps(mv_mincaps) { resize(n); }
38 ~mrvec() { free(map); }
39
40 int size() const { return dim; }
41 int capacity() const { return caps; }
42
43 bool empty() const { return dim==0; }
44 bool nempty() const { return dim!=0; }
45
46 T& at(int pos) { return map[pos]; }
47 const T& at(int pos) const { return map[pos]; }
48
49 T& operator[](int pos) { return map[pos]; }
50 const T& operator[](int pos) const { return map[pos]; }
51
52 iterator begin() { return map; }
53 const_iterator begin() const { return map; }
54
55 iterator end() { return map+dim; }
56 const_iterator end() const { return map+dim; }
57
58 T& front() { return map[0]; }
59 const T& front() const { return map[0]; }
60
61 T& back() { return map[dim?dim-1:0]; }
62 const T& back() const { return map[dim?dim-1:0]; }
63
64 ////////////////////////////////////////////////////////////////
65
66 void clear() { dim=0; }
67
68 iterator insert(iterator it,const T& s) {
69 int pos=it-map; ins(pos,1); return &(map[pos]=s);
70 }
71 void insert(iterator it,int n,const T& s) {
72 int pos=it-map; ins(pos,n); while(n--) map[pos++]=s;
73 }
74 void insert(iterator it,const_iterator p,const_iterator e) {
75 int pos=it-map; ins(pos,e-p); while(p<e) map[pos++]=*p++;
76 }
77 iterator erase(iterator it) {
78 int pos=it-map; ins(pos+1,-1); return map+pos;
79 }
80
81 void push_back(const T& s) { reserve(dim+1); map[dim++]=s; }
82 void pop_back(const T& s) { if(dim) --dim; }
83
84 ////////////////////////////////////////////////////////////////
85
86 void reserve(int n) {
87 if(caps<n) { while(caps<n) caps<<=1; map=(T*)realloc(map,caps*sizeof(T)); }
88 }
89 void resize(int n) { reserve(n); dim=n; }
90
91 ////////////////////////////////////////////////////////////////
92
93protected:
94 mrvec(const mrvec&) {}
95 void operator=(const mrvec&) {}
96
97 void ins(int pos,int n) {
98 if(n) { reserve(dim+n); memmove(map+pos+n,map+pos,(dim-pos)*sizeof(T)); dim+=n; }
99 }
100
101 T* map;
102 int dim,caps;
103};
104
105template <class T> class msvec : public mrvec<T> {
106public:
107 using mrvec<T>::map;
108 using mrvec<T>::dim;
109 typedef typename mrvec<T>::iterator iterator;
110 typedef typename mrvec<T>::const_iterator const_iterator;
111
112 msvec() : mrvec<T>() {}
113 msvec(int n) : mrvec<T>(n) { for(int i=0;i<dim;i++) new (map+i) T(); }
114 ~msvec() { while(dim) map[--dim].~T(); }
115
116 ////////////////////////////////////////////////////////////////
117
118 void clear() { while(dim) map[--dim].~T(); }
119
120 iterator insert(iterator it,const T& s) {
121 int pos=it-map; mrvec<T>::ins(pos,1); return new(map+pos) T(s);
122 }
123 void insert(iterator it,int n,const T& s) {
124 int pos=it-map; mrvec<T>::ins(pos,n); while(n--) new(map+pos++) T(s);
125 }
126 void insert(iterator it,const_iterator p,const_iterator e) {
127 int pos=it-map; mrvec<T>::ins(pos,e-p); while(p<e) new(map+pos++) T(*p++);
128 }
129 iterator erase(iterator it) {
130 it->~T(); int pos=it-map; mrvec<T>::ins(pos+1,-1); return map+pos;
131 }
132
133 void push_back(const T& s) { reserve(dim+1); new(map+dim++) T(s); }
134 void pop_back(const T& s) { if(dim) map[--dim].~T(); }
135
136 ////////////////////////////////////////////////////////////////
137
138 void resize(int n) {
139 while(dim>n) map[--dim].~T();
140 mrvec<T>::reserve(n);
141 while(dim<n) new (map+dim++) T();
142 }
143
144protected:
145 msvec(const msvec&) {}
146 void operator=(const msvec&) {}
147};
148
149#endif
diff --git a/src/mt/qran.h b/src/mt/qran.h
new file mode 100644
index 0000000..10f9a6f
--- /dev/null
+++ b/src/mt/qran.h
@@ -0,0 +1,34 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef QRANH
21#define QRANH
22
23#include <math.h>
24
25inline double QUniform(unsigned long& q) {
26 q=1664525L*q+1013904223L;
27 unsigned long long s=q;s<<=20;s|=(1023ULL<<52);return *(double*)&s-1;
28}
29inline int QRanBit(unsigned long& q) {
30 if(q&131072U) { q=((q^19U)<<1)|1U; return 1; }
31 else { q<<=1; return 0; }
32}
33
34#endif
diff --git a/src/mt/random.cc b/src/mt/random.cc
new file mode 100644
index 0000000..87a4c8c
--- /dev/null
+++ b/src/mt/random.cc
@@ -0,0 +1,95 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/random.h>
21#include <mt/mlock.h>
22#include <time.h>
23
24//////////////////////////////////////////////////////
25//
26// This file implements some routines from NumRec
27//
28
29const int NTAB=32; // NOTE: change in header if changing this
30
31const int IA=16807;
32const int IM=2147483647;
33const float AM=1/float(IM);
34const int IQ=127773;
35const int IR=2836;
36const int NDIV=1+(IM-1)/NTAB;
37const float EPS=1.2e-7;
38const float RNMX=1-EPS;
39
40static int idum,iy,iv[32],flag;
41static float extra;
42static int inited;
43static mutex_t mutex;
44
45unsigned long RandomInit(unsigned long seed)
46{
47 inited=1;
48 idum=seed?seed:1;
49 for(int j=NTAB+7;j>=0;j--) {
50 int k=idum/IQ;
51 idum=IA*(idum-k*IQ)-IR*k;
52 if(idum<0) idum+=IM;
53 if(j<NTAB) iv[j]=idum;
54 }
55 iy=iv[0];
56 return seed;
57}
58
59float Uniform()
60{
61 MLOCK(mutex);
62 if(!inited) RandomInit(time(0));
63 int k=idum/IQ;
64 idum=IA*(idum-k*IQ)-IR*k;
65 if(idum<0) idum+=IM;
66 int j=iy/NDIV;
67 iy=iv[j];
68 iv[j]=idum;
69 float temp=AM*iy; if(temp>RNMX) temp=RNMX;
70 return temp;
71}
72
73float Exponential()
74{
75 return -log(Uniform());
76}
77
78float Gaussian()
79{
80 MLOCK(mutex);
81 float v1,v2,rsq;
82 if(flag) {
83 flag=0;
84 return extra;
85 } else {
86 do {
87 v1=2*Uniform()-1;
88 v2=2*Uniform()-1;
89 rsq=v1*v1+v2*v2;
90 } while(rsq>=1||rsq<=0);
91 float fac=sqrt(-2*log(rsq)/rsq);
92 flag=1; extra=v1*fac;
93 return v2*fac;
94 }
95}
diff --git a/src/mt/random.h b/src/mt/random.h
new file mode 100644
index 0000000..196beae
--- /dev/null
+++ b/src/mt/random.h
@@ -0,0 +1,39 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef RANDOMH
21#define RANDOMH
22
23#include <mt/qran.h>
24
25///////////////////////////////////////////////////////////////////
26//
27// Uniform distribution ]x0..x1[
28//
29// Granularity approx 1.2e-7, ie more than 1e6 different values
30// Perodicity approx 1e8
31//
32
33unsigned long RandomInit(unsigned long seed);
34
35float Uniform();
36float Exponential();
37float Gaussian();
38
39#endif
diff --git a/src/mt/rfind_not_of.f b/src/mt/rfind_not_of.f
new file mode 100644
index 0000000..04a42d6
--- /dev/null
+++ b/src/mt/rfind_not_of.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function rfind_not_of(s,n,c)
21 byte s(0:1),c(0:1)
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=n-16,m,-16
25 if(c(s(i+15)).eq.0)go to 115
26 if(c(s(i+14)).eq.0)go to 114
27 if(c(s(i+13)).eq.0)go to 113
28 if(c(s(i+12)).eq.0)go to 112
29 if(c(s(i+11)).eq.0)go to 111
30 if(c(s(i+10)).eq.0)go to 110
31 if(c(s(i+9)).eq.0)go to 109
32 if(c(s(i+8)).eq.0)go to 108
33 if(c(s(i+7)).eq.0)go to 107
34 if(c(s(i+6)).eq.0)go to 106
35 if(c(s(i+5)).eq.0)go to 105
36 if(c(s(i+4)).eq.0)go to 104
37 if(c(s(i+3)).eq.0)go to 103
38 if(c(s(i+2)).eq.0)go to 102
39 if(c(s(i+1)).eq.0)go to 101
40 if(c(s(i)).eq.0)go to 100
41 10 continue
42 do 20 i=m-1,0,-1
43 if(c(s(i)).eq.0)go to 100
44 20 continue
45 rfind_not_of=-1
46 return
47 100 rfind_not_of=i
48 return
49 101 rfind_not_of=i+1
50 return
51 102 rfind_not_of=i+2
52 return
53 103 rfind_not_of=i+3
54 return
55 104 rfind_not_of=i+4
56 return
57 105 rfind_not_of=i+5
58 return
59 106 rfind_not_of=i+6
60 return
61 107 rfind_not_of=i+7
62 return
63 108 rfind_not_of=i+8
64 return
65 109 rfind_not_of=i+9
66 return
67 110 rfind_not_of=i+10
68 return
69 111 rfind_not_of=i+11
70 return
71 112 rfind_not_of=i+12
72 return
73 113 rfind_not_of=i+13
74 return
75 114 rfind_not_of=i+14
76 return
77 115 rfind_not_of=i+15
78 return
79 end
80
diff --git a/src/mt/rfind_of.f b/src/mt/rfind_of.f
new file mode 100644
index 0000000..5fa0931
--- /dev/null
+++ b/src/mt/rfind_of.f
@@ -0,0 +1,80 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function rfind_of(s,n,c)
21 byte s(0:1),c(0:1)
22 integer i,m,n
23 m=mod(n,16)
24 do 10 i=n-16,m,-16
25 if(c(s(i+15)).ne.0)go to 115
26 if(c(s(i+14)).ne.0)go to 114
27 if(c(s(i+13)).ne.0)go to 113
28 if(c(s(i+12)).ne.0)go to 112
29 if(c(s(i+11)).ne.0)go to 111
30 if(c(s(i+10)).ne.0)go to 110
31 if(c(s(i+9)).ne.0)go to 109
32 if(c(s(i+8)).ne.0)go to 108
33 if(c(s(i+7)).ne.0)go to 107
34 if(c(s(i+6)).ne.0)go to 106
35 if(c(s(i+5)).ne.0)go to 105
36 if(c(s(i+4)).ne.0)go to 104
37 if(c(s(i+3)).ne.0)go to 103
38 if(c(s(i+2)).ne.0)go to 102
39 if(c(s(i+1)).ne.0)go to 101
40 if(c(s(i)).ne.0)go to 100
41 10 continue
42 do 20 i=m-1,0,-1
43 if(c(s(i)).ne.0)go to 100
44 20 continue
45 rfind_of=-1
46 return
47 100 rfind_of=i
48 return
49 101 rfind_of=i+1
50 return
51 102 rfind_of=i+2
52 return
53 103 rfind_of=i+3
54 return
55 104 rfind_of=i+4
56 return
57 105 rfind_of=i+5
58 return
59 106 rfind_of=i+6
60 return
61 107 rfind_of=i+7
62 return
63 108 rfind_of=i+8
64 return
65 109 rfind_of=i+9
66 return
67 110 rfind_of=i+10
68 return
69 111 rfind_of=i+11
70 return
71 112 rfind_of=i+12
72 return
73 113 rfind_of=i+13
74 return
75 114 rfind_of=i+14
76 return
77 115 rfind_of=i+15
78 return
79 end
80
diff --git a/src/mt/scomptab.f b/src/mt/scomptab.f
new file mode 100644
index 0000000..4a8a286
--- /dev/null
+++ b/src/mt/scomptab.f
@@ -0,0 +1,44 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function scomptab(s,c,n,tab)
21 byte s(0:1),c(0:1),tab(0:1)
22 integer i,m,n
23 m=mod(n,4)
24 do 10 i=0,m-1
25 if(tab(s(i)).ne.tab(c(i)))go to 100
26 10 continue
27 do 20 i=m,n-1,4
28 if(tab(s(i)).ne.tab(c(i)))go to 100
29 if(tab(s(i+1)).ne.tab(c(i+1)))go to 101
30 if(tab(s(i+2)).ne.tab(c(i+2)))go to 102
31 if(tab(s(i+3)).ne.tab(c(i+3)))go to 103
32 20 continue
33 scomptab=0
34 return
35 100 scomptab=tab(s(i))-tab(c(i))
36 return
37 101 scomptab=tab(s(i+1))-tab(c(i+1))
38 return
39 102 scomptab=tab(s(i+2))-tab(c(i+2))
40 return
41 103 scomptab=tab(s(i+3))-tab(c(i+3))
42 return
43 end
44
diff --git a/src/mt/sconvert.f b/src/mt/sconvert.f
new file mode 100644
index 0000000..e887610
--- /dev/null
+++ b/src/mt/sconvert.f
@@ -0,0 +1,35 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 subroutine sconvert(s,sn,tab)
21 byte s(0:1),tab(0:1)
22 integer i,m,sn
23 m=mod(sn,4)
24 do 10 i=0,m-1
25 s(i)=tab(s(i))
26 10 continue
27 do 20 i=m,sn-1,4
28 s(i)=tab(s(i))
29 s(i+1)=tab(s(i+1))
30 s(i+2)=tab(s(i+2))
31 s(i+3)=tab(s(i+3))
32 20 continue
33 return
34 end
35
diff --git a/src/mt/sfind.f b/src/mt/sfind.f
new file mode 100644
index 0000000..2cc2954
--- /dev/null
+++ b/src/mt/sfind.f
@@ -0,0 +1,40 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function sfind(s,sn,c,cn)
21 character s(0:1),c(0:1)
22 integer i,j,m,sn,cn
23 m=mod(cn,4)
24 do 10 i=0,sn-1
25 do 20 j=0,m-1
26 if(s(i+j).ne.c(j))go to 50
27 20 continue
28 do 30 j=m,cn-1,4
29 if(s(i+j).ne.c(j))go to 50
30 if(s(i+j+1).ne.c(j+1))go to 50
31 if(s(i+j+2).ne.c(j+2))go to 50
32 if(s(i+j+3).ne.c(j+3))go to 50
33 30 continue
34 50 if(j.eq.cn)go to 100
35 10 continue
36 sfind=-1
37 return
38 100 sfind=i
39 return
40 end
diff --git a/src/mt/sfindtab.f b/src/mt/sfindtab.f
new file mode 100644
index 0000000..b4e148e
--- /dev/null
+++ b/src/mt/sfindtab.f
@@ -0,0 +1,40 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function sfindtab(s,sn,c,cn,tab)
21 byte s(0:1),c(0:1),tab(0:1)
22 integer i,j,m,sn,cn
23 m=mod(cn,4)
24 do 10 i=0,sn-1
25 do 20 j=0,m-1
26 if(tab(s(i+j)).ne.tab(c(j)))go to 50
27 20 continue
28 do 30 j=m,cn-1,4
29 if(tab(s(i+j)).ne.tab(c(j)))go to 50
30 if(tab(s(i+j+1)).ne.tab(c(j+1)))go to 50
31 if(tab(s(i+j+2)).ne.tab(c(j+2)))go to 50
32 if(tab(s(i+j+3)).ne.tab(c(j+3)))go to 50
33 30 continue
34 50 if(j.eq.cn)go to 100
35 10 continue
36 sfindtab=-1
37 return
38 100 sfindtab=i
39 return
40 end
diff --git a/src/mt/skip_parentesis.f b/src/mt/skip_parentesis.f
new file mode 100644
index 0000000..1104c8f
--- /dev/null
+++ b/src/mt/skip_parentesis.f
@@ -0,0 +1,42 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function skip_parentesis(s,n,left,right,esc)
21 character s(0:1),left,right,esc
22 integer i,n,cnt
23 if(n.eq.0)go to 40
24 if(s(0).ne.left)go to 40
25 cnt=1
26 do 10 i=1,n-1
27 if(s(i-1).eq.esc)go to 10
28 if(s(i).eq.right)then
29 cnt=cnt-1
30 if(cnt.eq.0)go to 30
31 else if(s(i).eq.left)then
32 cnt=cnt+1
33 end if
34 10 continue
35 20 skip_parentesis=-1
36 return
37 30 skip_parentesis=i+1
38 return
39 40 skip_parentesis=0
40 return
41 end
42
diff --git a/src/mt/split.h b/src/mt/split.h
new file mode 100644
index 0000000..52e66e3
--- /dev/null
+++ b/src/mt/split.h
@@ -0,0 +1,72 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef MSPLITH
21#define MSPLITH
22
23#include <mt/stringref.h>
24
25inline sref Skip(const sref& a,const charset& ws=cset_ws) {
26 return a.right_first_not_of(ws);
27}
28
29inline sref Trim(const sref& a,const charset& ws=cset_ws) {
30 return a.right_first_not_of(ws).leftand_last_not_of(ws);
31}
32
33inline sref Trim(const sref& a,const bracket& enc,const charset& ws=cset_ws) {
34 sref s=a.right_first_not_of(ws).leftand_last_not_of(ws);
35 while(s.nempty()&&s.skip(enc)==s.size())
36 s=s(1,-3).right_first_not_of(ws).leftand_last_not_of(ws);
37 return s;
38}
39
40inline sref First(const sref& a,const charset& ws=cset_ws) {
41 return a.right_first_not_of(ws).left_first_of(ws);
42}
43
44inline sref Rest(const sref& a,const charset& ws=cset_ws) {
45 return a.right_first_not_of(ws).right_first_of(ws).right_first_not_of(ws);
46}
47
48inline sref Last(const sref& a,const charset& ws=cset_ws) {
49 sref p=a.leftand_last_not_of(ws);
50 sref e=p.past_last_of(ws);
51 return e.nempty()?e:p;
52}
53
54inline int Split(sref& first,sref& rest,const charset& ws=cset_ws) {
55 rest=rest.right_first_not_of(ws);
56 int s=rest.find_of(ws);
57 first=rest.left(s);
58 rest=rest.right(s);
59 return first.nempty();
60}
61
62inline int Splitln(sref& first,sref& rest) {
63 int s=rest.find_of(cset_newl);
64 first=rest.left(s);
65 rest=rest.right(s).past_nl();
66 return first.begin()!=rest.begin();
67}
68
69typedef int (*split_t)(sref& first,sref& rest);
70
71#endif
72
diff --git a/src/mt/srfind.f b/src/mt/srfind.f
new file mode 100644
index 0000000..24f4fb4
--- /dev/null
+++ b/src/mt/srfind.f
@@ -0,0 +1,40 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function srfind(s,sn,c,cn)
21 character s(0:1),c(0:1)
22 integer i,j,m,sn,cn
23 m=mod(cn,4)
24 do 10 i=sn-1,0,-1
25 do 20 j=0,m-1
26 if(s(i+j).ne.c(j))go to 50
27 20 continue
28 do 30 j=m,cn-1,4
29 if(s(i+j).ne.c(j))go to 50
30 if(s(i+j+1).ne.c(j+1))go to 50
31 if(s(i+j+2).ne.c(j+2))go to 50
32 if(s(i+j+3).ne.c(j+3))go to 50
33 30 continue
34 50 if(j.eq.cn)go to 100
35 10 continue
36 srfind=-1
37 return
38 100 srfind=i
39 return
40 end
diff --git a/src/mt/srfindtab.f b/src/mt/srfindtab.f
new file mode 100644
index 0000000..ad5fdd4
--- /dev/null
+++ b/src/mt/srfindtab.f
@@ -0,0 +1,40 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function srfindtab(s,sn,c,cn,tab)
21 byte s(0:1),c(0:1),tab(0:1)
22 integer i,j,m,sn,cn
23 m=mod(cn,4)
24 do 10 i=sn-1,0,-1
25 do 20 j=0,m-1
26 if(tab(s(i+j)).ne.tab(c(j)))go to 50
27 20 continue
28 do 30 j=m,cn-1,4
29 if(tab(s(i+j)).ne.tab(c(j)))go to 50
30 if(tab(s(i+j+1)).ne.tab(c(j+1)))go to 50
31 if(tab(s(i+j+2)).ne.tab(c(j+2)))go to 50
32 if(tab(s(i+j+3)).ne.tab(c(j+3)))go to 50
33 30 continue
34 50 if(j.eq.cn)go to 100
35 10 continue
36 srfindtab=-1
37 return
38 100 srfindtab=i
39 return
40 end
diff --git a/src/mt/stackque.h b/src/mt/stackque.h
new file mode 100644
index 0000000..349cb4f
--- /dev/null
+++ b/src/mt/stackque.h
@@ -0,0 +1,64 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef STACKQUEH
21#define STACKQUEH
22
23#include <mt/mstring.h>
24#include <mt/mlock.h>
25
26template <class T> class stackque {
27public:
28 stackque(int m) {
29 put=get=n=0;
30 base=new T[caps=m];
31 memset(&mutex,0,sizeof(mutex_t));
32 }
33 ~stackque() { delete base; }
34
35 int push(const T& a) throw(merror_t) {
36 MLOCK(mutex);
37 if(n>=caps) THROW("stackque: Full");
38 base[put++]=a;
39 if(put==caps) put=0;
40 return ++n;
41 }
42
43 int pop(T& a) {
44 MLOCK(mutex);
45 if(n) {
46 a=base[get++];
47 if(get==caps) get=0;
48 return n--;
49 }
50 else return 0;
51 }
52
53 int capacity() const { return caps; }
54 int size() const { return n; }
55 int empty() const { return n==0; }
56 int full() const { return n==caps; }
57 void clear() { put=get=n=0; }
58private:
59 int put,get,n,caps;
60 T* base;
61 mutex_t mutex;
62};
63
64#endif
diff --git a/src/mt/stringref.cc b/src/mt/stringref.cc
new file mode 100644
index 0000000..66b3d3e
--- /dev/null
+++ b/src/mt/stringref.cc
@@ -0,0 +1,126 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/stringref.h>
21#include <unistd.h>
22#include <fcntl.h>
23
24extern "C" {
25 int cfind_(const char* s,const int& sn,const char& c);
26 int crfind_(const char* s,const int& sn,const char& c);
27 int sfind_(const char* s,const int& sn,const char* c,const int& cn);
28 int srfind_(const char* s,const int& sn,const char* c,const int& cn);
29 int sfindtab_(const char* s,const int& sn,const char* c,const int& cn,const char* tab);
30 int srfindtab_(const char* s,const int& sn,const char* c,const int& cn,const char* tab);
31 int scomptab_(const char* s,const char* c,const int& n,const char* tab);
32 void sconvert_(char* s,const int& sn,const char* tab);
33 int find_of__(const char* s,const int& sn,const char* set);
34 int rfind_of__(const char* s,const int& sn,const char* set);
35 int find_not_of__(const char* s,const int& sn,const char* set);
36 int rfind_not_of__(const char* s,const int& sn,const char* set);
37 int skip_parentesis__(const char* s,const int& sn,
38 const char& left,const char& right,const char& esc);
39 int strip_(char* s,const char* c,const int& cn,const char& esc);
40}
41
42////////////////////////////////////////////////////
43
44char* sref::copyto(char* buf,int max) const {
45 if(!dim) buf[0]=0;
46 else if(dim<max) ((char*)memcpy(buf,map,dim))[dim]=0;
47 else ((char*)memcpy(buf,map,max-1))[max-1]=0;
48 return buf;
49}
50
51int sref::compare(const sref& s,const charmap& tab) const {
52 int c; if(map==s.map) return dim-s.dim;
53 else return (c=scomptab_(map,s.map,dim<s.dim?dim:s.dim,tab.map))?c:dim-s.dim;
54}
55
56////////////////////////////////////////////////////
57
58void sref::tolower() { sconvert_(map,dim,cset_lcase.map); }
59void sref::toupper() { sconvert_(map,dim,cset_ucase.map); }
60void sref::tosim(const charmap& s) { sconvert_(map,dim,s.map); }
61
62////////////////////////////////////////////////////
63
64sref sref::operator()(int pos,int n) const {
65 if(pos<0) { pos+=dim; if(pos<0) pos=0; }
66 if(pos>=dim) return sref(map+dim,0);
67 else {
68 if(n<0) { n+=dim+1; if(n<0) n=0; }
69 if(n>=dim-pos) return sref(map+pos,dim-pos);
70 else return sref(map+pos,n);
71 }
72}
73
74sref sref::left(int n) const {
75 if(n<0) { n+=dim+1; if(n<0) n=0; }
76 if(n>dim) return sref(map,dim);
77 else return sref(map,n);
78}
79sref sref::leftand(int n,int m) const {
80 if(n<0) { n+=dim+1; if(n<0) n=0; }
81 if((n+=m)>dim) return sref(map,dim);
82 else return sref(map,n);
83}
84sref sref::right(int n) const {
85 if(n<0) { n+=dim+1; if(n<0) n=0; }
86 if(n>dim) return sref(map+dim,0);
87 else return sref(map+n,dim-n);
88}
89sref sref::past(int n,int m) const {
90 if(n<0) { n+=dim+1; if(n<0) n=0; }
91 if((n+=m)>dim) return sref(map+dim,0);
92 else return sref(map+n,dim-n);
93}
94
95////////////////////////////////////////////////////////////////
96
97int sref::find(char c) const { return cfind_(map,dim,c); }
98int sref::rfind(char c) const { return crfind_(map,dim,c); }
99int sref::find(const sref& s) const { return sfind_(map,dim,s.map,s.dim); }
100int sref::rfind(const sref& s) const { return srfind_(map,dim,s.map,s.dim); }
101int sref::find(const sref& s,const charmap& tab) const {
102 return sfindtab_(map,dim,s.map,s.dim,tab.map);
103}
104int sref::rfind(const sref& s,const charmap& tab) const {
105 return srfindtab_(map,dim,s.map,s.dim,tab.map);
106}
107
108int sref::find_of(const charset& s) const { return find_of__(map,dim,s.map); }
109int sref::rfind_of(const charset& s) const { return rfind_of__(map,dim,s.map); }
110int sref::find_not_of(const charset& s) const { return find_not_of__(map,dim,s.map); }
111int sref::rfind_not_of(const charset& s) const { return rfind_not_of__(map,dim,s.map); }
112
113int sref::skip(const bracket& bra) const {
114 return skip_parentesis__(map,dim,bra.left,bra.right,bra.esc);
115}
116
117////////////////////////////////////////////////////////////////
118
119int sref::save(const sref& s,int prot) const {
120 sref_t path; s.copyto(path);
121 int fd=open(path,O_WRONLY|O_CREAT,prot);
122 if(fd<0) return -1;
123 write(fd,map,dim);
124 close(fd);
125 return dim;
126}
diff --git a/src/mt/stringref.h b/src/mt/stringref.h
new file mode 100644
index 0000000..a66ac21
--- /dev/null
+++ b/src/mt/stringref.h
@@ -0,0 +1,239 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef SREFH
21#define SREFH
22
23#include <mt/charset.h>
24#include <stdlib.h>
25
26typedef char sref_t[1024];
27
28class sref {
29public:
30 sref() : map((char*)&dim),dim(0) {}
31 explicit sref(char* p) : map(p),dim(strlen(p)) {}
32 explicit sref(const char* p) : map((char*)p),dim(strlen(p)) {}
33 sref(char* p,int n) : map(p),dim(n) {}
34 sref(const char* p,int n) : map((char*)p),dim(n) {}
35
36 int size() const { return dim; }
37 bool empty() const { return dim==0; }
38 bool nempty() const { return dim!=0; }
39
40 char* data() { return map; }
41 const char* data() const { return map; }
42
43 char& operator[](int pos) { return map[pos]; }
44 const char& operator[](int pos) const { return map[pos]; }
45
46 char* begin() { return map; }
47 const char* begin() const { return map; }
48
49 char* end() { return map+dim; }
50 const char* end() const { return map+dim; }
51
52 int operator*() const { return dim?*map:0; }
53 int front() const { return dim?*map:0; }
54 int back() const { return dim?map[dim-1]:0; }
55
56 ////////////////////////////////////////////////////////////////
57
58 sref popf() const { return dim?sref(map+1,dim-1):*this; }
59 sref popb() const { return dim?sref(map,dim-1):*this; }
60
61 sref adv(int n) const { return n>0?(n<dim?sref(map+n,dim-n):sref(map+dim,0)):*this; }
62
63 // NOTE that these functions are LOW LEVEL - no checks!
64
65 sref adv(const sref& s) const { return sref(s.end(),end()-s.end()); }
66 sref operator()(char* p) { return sref(p,map+dim-p); }
67 const sref operator()(const char* p) const { return sref((char*)p,map+dim-p); }
68
69 ////////////////////////////////////////////////////////////////
70
71 char* news() const {char* s=new char[dim+1];s[dim]=0;return (char*)memcpy(s,map,dim); }
72
73 void clear() {dim=0;}
74
75 ////////////////////////////////////////////////////////////////
76
77 void mcopy(const sref& s) {
78 if(s.dim<dim) memmove(map,s.map,dim=s.dim); else memmove(map,s.map,dim);
79 }
80
81 void tolower();
82 void toupper();
83 void tosim(const charmap& s=cset_sim);
84
85 ////////////////////////////////////////////////////////////////
86
87 char* copyto(char* buf,int max) const;
88 char* copyto(sref_t& buf) const { return copyto(buf,sizeof(buf)); }
89
90 int compare(const sref& s) const {
91 int c; if(map==s.map) return dim-s.dim;
92 else return (c=memcmp(map,s.map,dim<s.dim?dim:s.dim))?c:dim-s.dim;
93 }
94 int compare(const sref& s,const charmap& tab) const;
95
96 ////////////////////////////////////////////////////////////////
97
98 sref operator()(int pos,int n=-1) const;
99 sref left(int n) const;
100 sref leftand(int n,int m) const;
101 sref right(int n) const;
102 sref past(int n,int m) const;
103
104 sref past_nl() const { return past(find('\n'),1); }
105
106 ////////////////////////////////////////////////////////////////
107
108 int find(char c) const;
109 sref left_first(char c) const { return left(find(c)); }
110 sref leftand_first(char c) const { return leftand(find(c),1); }
111 sref right_first(char c) const { return right(find(c)); }
112 sref past_first(char c) const { return past(find(c),1); }
113
114 int rfind(char c) const;
115 sref left_last(char c) const { return left(rfind(c)); }
116 sref leftand_last(char c) const { return leftand(rfind(c),1); }
117 sref right_last(char c) const { return right(rfind(c)); }
118 sref past_last(char c) const { return past(rfind(c),1); }
119
120 int find(const sref& s) const;
121 sref left_first(const sref& s) const { return left(find(s)); }
122 sref leftand_first(const sref& s) const { return leftand(find(s),s.size()); }
123 sref right_first(const sref& s) const { return right(find(s)); }
124 sref past_first(const sref& s) const { return past(find(s),s.size()); }
125
126 int rfind(const sref& s) const;
127 sref left_last(const sref& s) const { return left(rfind(s)); }
128 sref leftand_last(const sref& s) const { return leftand(rfind(s),s.size()); }
129 sref right_last(const sref& s) const { return right(rfind(s)); }
130 sref past_last(const sref& s) const { return past(rfind(s),s.size()); }
131
132 int find(const sref& s,const charmap& tab) const;
133 sref left_first(const sref& s,const charmap& tab) const { return left(find(s,tab)); }
134 sref leftand_first(const sref& s,const charmap& tab)const{
135 return leftand(find(s,tab),s.size());
136 }
137 sref right_first(const sref& s,const charmap& tab) const { return right(find(s,tab)); }
138 sref past_first(const sref& s,const charmap& tab) const {
139 return past(find(s,tab),s.size());
140 }
141
142 int rfind(const sref& s,const charmap& tab) const;
143 sref left_last(const sref& s,const charmap& tab) const { return left(rfind(s,tab)); }
144 sref leftand_last(const sref& s,const charmap& tab)const{
145 return leftand(rfind(s,tab),s.size());
146 }
147 sref right_last(const sref& s,const charmap& tab) const { return right(rfind(s,tab)); }
148 sref past_last(const sref& s,const charmap& tab) const {
149 return past(rfind(s,tab),s.size());
150 }
151
152 int find_of(const charset& s) const;
153 sref left_first_of(const charset& s) const { return left(find_of(s)); }
154 sref leftand_first_of(const charset& s) const { return leftand(find_of(s),1); }
155 sref right_first_of(const charset& s) const { return right(find_of(s)); }
156 sref past_first_of(const charset& s) const { return past(find_of(s),1); }
157
158 int rfind_of(const charset& s) const;
159 sref left_last_of(const charset& s) const { return left(rfind_of(s)); }
160 sref leftand_last_of(const charset& s) const { return leftand(rfind_of(s),1); }
161 sref right_last_of(const charset& s) const { return right(rfind_of(s)); }
162 sref past_last_of(const charset& s) const { return past(rfind_of(s),1); }
163
164 int find_not_of(const charset& s) const;
165 sref left_first_not_of(const charset& s) const { return left(find_not_of(s)); }
166 sref leftand_first_not_of(const charset& s) const { return leftand(find_not_of(s),1); }
167 sref right_first_not_of(const charset& s) const { return right(find_not_of(s)); }
168 sref past_first_not_of(const charset& s) const { return past(find_not_of(s),1); }
169
170 int rfind_not_of(const charset& s) const;
171 sref left_last_not_of(const charset& s) const { return left(rfind_not_of(s)); }
172 sref leftand_last_not_of(const charset& s) const { return leftand(rfind_not_of(s),1); }
173 sref right_last_not_of(const charset& s) const { return right(rfind_not_of(s)); }
174 sref past_last_not_of(const charset& s) const { return past(rfind_not_of(s),1); }
175
176 int skip(const bracket& bra) const;
177
178 ////////////////////////////////////////////////////////////////
179
180 int save(const sref& path,int prot=0600) const;
181
182protected:
183 char* map;
184 int dim;
185};
186
187////////////////////////////////////////////////////
188
189inline bool operator<(const sref& a,const sref& b) {
190 return a.compare(b)<0;
191}
192inline bool operator<=(const sref& a,const sref& b) {
193 return a.compare(b)<=0;
194}
195inline bool operator==(const sref& a,const sref& b) {
196 return a.compare(b)==0;
197}
198inline bool operator!=(const sref& a,const sref& b) {
199 return a.compare(b)!=0;
200}
201inline bool operator>=(const sref& a,const sref& b) {
202 return a.compare(b)>=0;
203}
204inline bool operator>(const sref& a,const sref& b) {
205 return a.compare(b)>0;
206}
207
208//////////////////////////////////////////////////////////////////////////
209
210inline int operator-(const sref& a,const sref& b) { return a.data()-b.data(); }
211
212//////////////////////////////////////////////////////////////////////////
213
214inline int ltn(const sref& a,const sref& b) {
215 return a.compare(b,cset_lcase)<0;
216}
217inline int len(const sref& a,const sref& b) {
218 return a.compare(b,cset_lcase)<=0;
219}
220inline int eqn(const sref& a,const sref& b) {
221 return a.compare(b,cset_lcase)==0;
222}
223inline int nen(const sref& a,const sref& b) {
224 return a.compare(b,cset_lcase)!=0;
225}
226inline int gen(const sref& a,const sref& b) {
227 return a.compare(b,cset_lcase)>=0;
228}
229inline int gtn(const sref& a,const sref& b) {
230 return a.compare(b,cset_lcase)>0;
231}
232
233//////////////////////////////////////////////////////////////////////////
234
235inline int atob(const sref& s) { sref_t buf; return atoi(s.copyto(buf))!=0; }
236inline int atoi(const sref& s) { sref_t buf; return atoi(s.copyto(buf)); }
237inline double atof(const sref& s) { sref_t buf; return atof(s.copyto(buf)); }
238
239#endif
diff --git a/src/mt/strip.f b/src/mt/strip.f
new file mode 100644
index 0000000..1cca9c4
--- /dev/null
+++ b/src/mt/strip.f
@@ -0,0 +1,31 @@
1ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2c
3c HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4c
5c This program is free software; you can redistribute it and/or modify
6c it under the terms of the GNU General Public License as published by
7c the Free Software Foundation; either version 2 of the License, or
8c (at your option) any later version.
9c
10c This program is distributed in the hope that it will be useful,
11c but WITHOUT ANY WARRANTY; without even the implied warranty of
12c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c GNU General Public License for more details.
14c
15c You should have received a copy of the GNU General Public License
16c along with this program; if not, write to the Free Software
17c Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18c
19
20 integer function strip(s,c,cn,esc)
21 character s(0:1),c(0:1),esc
22 integer i,j,cn
23 j=0
24 do 10 i=0,cn-1
25 if(c(i).eq.esc)go to 10
26 s(j)=c(i)
27 j=j+1
28 10 continue
29 strip=j
30 return
31 end
diff --git a/src/mt/test.cc b/src/mt/test.cc
new file mode 100644
index 0000000..5671a33
--- /dev/null
+++ b/src/mt/test.cc
@@ -0,0 +1,337 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/uniheap.h>
21#include <mt/stackque.h>
22#include <mt/random.h>
23#include <mt/lookup.h>
24#include <mt/mset.h>
25#include <mt/issue.h>
26#include <mt/mvec.h>
27#include <mt/msmap.h>
28#include <time.h>
29
30#define GENERAL 0
31#define STREAM 1
32#define HEAPS 0
33#define CHARSET 0
34#define RANDOM 0
35#define LOOKUP 0
36#define ISSUE 1
37#define MSET 0
38#define CVTS 0
39#define VECTOR 0
40#define MSMAP 0
41
42static fp_stream mout(stdout),merr(stderr);
43
44main(int argc,char* argv[])
45{
46 mstring s;
47#if GENERAL
48 s="asdfwerfindfindis?? asdf wert nnvnbn\n";
49
50 mout<<"["<<Trim(s,cset_para)<<"]\n";
51
52 sref find=sref("find");
53 sref rfind=sref("rfind");
54
55 mout<<s.find(find)<<"\n";
56 mout<<s.rfind(rfind)<<"\n";
57 mout<<s.find(find,cset_lcase)<<"\n";
58 mout<<s.rfind(rfind,cset_lcase)<<"\n";
59 mout<<s.find(find,cset_ucase)<<"\n";
60 mout<<s.rfind(rfind,cset_ucase)<<"\n";
61
62 mout<<"****\n";
63
64 mout<<"["<<s.leftand_last_not_of(cset_ws)<<"]\n";
65
66 mout<<"****\n";
67
68 s.tolower();
69 mout<<"["<<s<<"]\n";
70 s.toupper();
71 mout<<"["<<s<<"]\n";
72
73 mout<<"*****\n";
74
75 mstring st="abcdefghi2jklmn";
76 charset stset("123");
77 mout<<"["<<st.left_first_of(stset)<<"]\n";
78 mout<<"["<<st.right_first_of(stset)<<"]\n";
79 mout<<"["<<st.past_first_of(stset)<<"]\n";
80
81 mout<<"******\n";
82
83 mstring a=First(s);
84 mstring b=Rest(s);
85 mstring c=Last(s);
86 mout<<"["<<a<<"]\n";
87 mout<<"["<<b<<"]\n";
88 mout<<"["<<c<<"]\n";
89
90 mout<<"******\n";
91
92 sref first,rest=s;
93 while(Split(first,rest)) {
94 mout<<"["<<first<<"]["<<atoi(first)<<"]\n";
95 }
96
97 mout<<"*******\n";
98
99 mout<<"["<<mstring().convert("%d %02X",56,100)<<"]\n";
100
101 mout<<s.skip(cset_para)<<"\n";
102
103 mout<<"********\n";
104
105 //mstring buf; buf.load("tt.cc");
106 //mout<<"***\n"<<buf<<"***\n";
107#endif
108#if STREAM
109 s="more strange asdf\n";
110
111 swrite to;
112 mout<<s<<"\n";
113 to.hold(s)<<" Hello! this is appending "<<4<<" to string\n";
114 mout<<s<<"\n";
115
116 mout<<"********\n";
117
118 mstream mm; mm<<"Hejsan!\n";
119
120 mout<<"********\n";
121
122 try {
123 THROW("hello "<<4<<" once more");
124 }
125 catch(const merror_t& e) {
126 mout<<"Error test: "<<e.num<<"\n";
127 mout<<e.desc<<"\n";
128 }
129
130 mout<<"********\n";
131
132 sref sa=s;
133 sref sb=s;
134 mout<<(sa==sb)<<"\n";
135
136 mout<<"********\n";
137
138 mstring tt="(asdf)sdfsdf";
139 mout<<tt.skip(cset_para)<<"\n";
140 mout<<"["<<tt(1,tt.skip(cset_para)-2)<<"]\n";
141
142 mout<<"********\n";
143#endif
144
145#if HEAPS
146
147 uniheap<4> stack; stack.init();
148 for(int i=0;i<48;i++) {
149 //stack.pop(stack.push());
150 stack.push();
151 }
152 mout<<"--\n";
153 mout<<stack.chunksize()<<"\n";
154
155 mout<<"********\n";
156
157 stackque<int> que(8);
158 for(int i=0;i<8;i++) que.push(i);
159
160 try {
161 que.push(5);
162 }
163 catch(const merror_t& e) {
164 merr<<e.num<<"\n";
165 merr<<e.desc<<"\n";
166 }
167
168 int pop;
169 while(que.pop(pop)) merr<<pop<<"\n";
170
171#endif
172
173#if CHARSET
174
175 charset set("12345öd");
176 charset set2("12");
177 charset set3=set-set2;
178
179 merr<<"* \n";
180
181 for(int i=-127;i<127;i++) {
182 if(set.map[i]) mout<<i<<"("<<char(i)<<")\n";
183 }
184
185 merr<<"* \n";
186
187 for(int i=-127;i<127;i++) {
188 if(set3.map[i]) mout<<i<<"("<<char(i)<<")\n";
189 }
190
191 merr<<"**\n";
192
193 mout<<find_of_("ö",1,set.map)<<"\n";
194 mout<<s.find_of(set)<<"\n";
195
196 mout<<"***\n";
197
198 mout<<"[";
199 for(int i=-127;i<128;i++) if(cset_lcase[i]!=i) mout.put(i);
200 mout<<"]\n";
201 mout<<"[";
202 for(int i=-127;i<128;i++) if(cset_lcase[i]!=i) mout.put(cset_lcase[i]);
203 mout<<"]\n";
204
205 mout<<"\n";
206
207 mout<<"[";
208 for(int i=-127;i<128;i++) if(cset_ueqv1[i]!=i) mout.put(i);
209 mout<<"]\n";
210 mout<<"[";
211 for(int i=-127;i<128;i++) if(cset_ueqv1[i]!=i) mout.put(cset_ueqv1[i]);
212 mout<<"]\n";
213
214 mout<<"\n";
215
216 mout<<"[";
217 for(int i=-127;i<128;i++) if(cset_ueqv2[i]!=i) mout.put(i);
218 mout<<"]\n";
219 mout<<"[";
220 for(int i=-127;i<128;i++) if(cset_ueqv2[i]!=i) mout.put(cset_ueqv2[i]);
221 mout<<"]\n";
222
223 mout<<"\n";
224
225 mout<<"[";
226 for(int i=-127;i<128;i++) if(cset_sim[i]!=i) mout.put(i);
227 mout<<"]\n";
228 mout<<"[";
229 for(int i=-127;i<128;i++) if(cset_sim[i]!=i) mout.put(cset_sim[i]);
230 mout<<"]\n";
231#endif
232
233#if RANDOM
234 RandomInit(13);
235 for(int i=0;i<100;i++) mout<<Uniform()<<"\n";
236#endif
237
238#if LOOKUP
239
240 while(1) {
241 mstring ip;
242 merr<<"addr>";
243 getline(ip,stdin);
244 IPnode node;
245 for(int i=0;i<4;i++) {
246 if(Lookup(node,ip)) {
247 merr<<node.valid<<"\n";
248 merr<<node.ip<<"\n";
249 merr<<node.name<<"\n";
250 }
251 else {
252 merr<<"Not found\n";
253 break;
254 }
255 }
256 }
257
258#endif
259
260#if ISSUE
261
262 issue_t cmd(sref("/bin/cat"));
263 mswrite out;
264 mstring in="hello world!";
265 cmd.run(out,in);
266 mout<<"Got ["<<out.str()<<"]\n";
267
268 cmd.clear();
269 cmd.add(sref("sadfasfd"));
270 cmd.end();
271 out.clear();
272 cmd.run(out,in);
273 mout<<"Got ["<<out.str()<<"]\n";
274
275#endif
276
277#if MSET
278
279 mstring mm="hello world!\n how many items?\n";
280 mset a=mm;
281 for(int i=0;i<a.size();i++) {
282 mout<<a[i]<<"\n";
283 }
284
285 mout<<"OR ["<<a<<"]\n";
286
287#endif
288
289#if CVTS
290
291 merr<<"n: "<<itoa(5)<<"\n";
292 merr<<"f: "<<ftoa(5)<<"\n";
293 merr<<"f: "<<ftoa(5.7)<<"\n";
294 merr<<"f: "<<ftoa(-3)<<"\n";
295 merr<<"f: "<<ftoa(3.78678)<<"\n";
296 merr<<"f: "<<ftoa(exp(2.1))<<"\n";
297 merr<<"f: "<<ftoa(time(0))<<"\n";
298 merr<<"direct: "<<3.40000<<"\n";
299
300 pipe_stream tout(1);
301 tout<<"How does this one "<<-78.4<<" behave??\n";
302
303 mstring inp;
304 getline(inp,stdin);
305 merr<<ftoa(atof(inp))<<"\n";
306
307#endif
308
309#if VECTOR
310
311 mrvec<int> v(4);
312 for(int i=0;i<v.size();i++) v[i]=i;
313
314 for(int i=0;i<v.size();i++) merr<<v[i]<<"\n";
315
316#endif
317
318#if MSMAP
319
320 ssmap map;
321 //map.add("hello","world");
322 //map.add("one","world!");
323 map.push_back(sstring("one","world!"));
324 map.push_back(sstring("hello","world"));
325 map.sort();
326
327 for(ssmap::iterator p=map.begin();p!=map.end();p++) {
328 merr<<p->first<<" "<<p->second<<"\n";
329 }
330
331 const mstring* p=map.get("one");
332 if(p) merr<<"got "<<*p<<"\n";
333
334#endif
335
336 return 0;
337}
diff --git a/src/mt/uniheap.h b/src/mt/uniheap.h
new file mode 100644
index 0000000..39c3d34
--- /dev/null
+++ b/src/mt/uniheap.h
@@ -0,0 +1,65 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef UNIHEAPH
21#define UNIHEAPH
22
23#include <mt/mlock.h>
24#include <malloc.h>
25#include <string.h>
26
27// NOTE - must be in extern/static scope, or zeroed before use
28// by a call to init. constructors will fail badly.
29// A minimum of sizeof(T)==4 is required.
30// Furthermore, the upper limit of heap space is 1Gb.
31
32template <int N> class uniheap {
33public:
34 static const int maxchunks=24;
35
36 void init() {
37 head=0;
38 chunk=0;
39 nchunks=0;
40 memset(&mutex,0,sizeof(mutex_t));
41 }
42
43 char* push() { MLOCK(mutex); char* p=news(); head=*(char**)p; return p; }
44 void pop(void* p) { MLOCK(mutex); *((char**)p)=head; head=(char*)p; }
45 int chunksize() const { return chunk; }
46protected:
47 char* news() {
48 if(!head) {
49 if(!chunk) chunk=N<<4;
50 if(nchunks>=maxchunks) throw((int)0);
51 head=chunks[nchunks++]=(char*)malloc(chunk);
52 if(!head) throw((int)0);
53 for(int i=0;i<chunk-N;i+=N) *((char**)(head+i))=head+i+N;
54 *((char**)(head+chunk-N))=0;
55 chunk<<=1;
56 }
57 return head;
58 }
59private:
60 char *head,*chunks[maxchunks];
61 int chunk,nchunks;
62 mutex_t mutex;
63};
64
65#endif
diff --git a/src/net/htcd.cc b/src/net/htcd.cc
new file mode 100644
index 0000000..89729e6
--- /dev/null
+++ b/src/net/htcd.cc
@@ -0,0 +1,153 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/thrserv.h>
21
22static fp_stream merr(stderr);
23
24static mstring PATH;
25static htcServ* SERV;
26
27const mstring PIDURI="/sys/htcd";
28
29const int BACKLOG=4;
30const int SERVERS=9;
31const int LOWER=3;
32const int UPPER=6;
33const int KEEPALIVE=300;
34const int SNDBUFSIZE=16384;
35const int RCVBUFSIZE=16384;
36
37///////////////////////////////////////////////////////////
38
39static thrServ* server[SERVERS];
40static thrCron* crontab;
41
42extern "C" {
43 static void* thr_handler(void* p) { ((thrServ*)p)->enter(); return 0; }
44 static void* thr_cron(void* p) { ((thrCron*)p)->enter(); return 0; }
45 static void onTERM(int sig) { SERV->htcd.running=0; }
46 static void onHUP(int sig) { if(crontab) crontab->running=0; }
47 typedef void (*disp_t)(int);
48}
49
50static void MainProc(isocket& sock)
51{
52 int keep=1;
53 while(SERV->htcd.running) {
54 int nvacant=0; for(int i=0;i<SERVERS;i++) if(server[i]->vacant()) nvacant++;
55 if(nvacant>UPPER) keep=1; else if(nvacant<=LOWER) keep=0;
56 if(!keep) for(int i=0;i<SERVERS;i++) server[i]->shutdown();
57 time_t timeout=time(0)-KEEPALIVE;
58 for(int i=0;i<SERVERS;i++) if(timeout>server[i]->last) server[i]->disconnect();
59 int test=sock.test();
60 if(test>0) {
61 thrServ* p=0;
62 for(int i=0;i<SERVERS;i++) if(server[i]->vacant()) { p=server[i]; break; }
63 if(!p) for(int i=0;i<SERVERS;i++) if(!p||server[i]->first<p->first) p=server[i];
64 if(p->shutdown()) {
65 try {
66 isocket* s=sock.accept();
67 if(s) p->reset(s,keep);
68 }
69 catch(const merror_t& e) {
70 merr<<"SOCKET: "<<e.desc<<"\n";
71 }
72 }
73 }
74 else if(test<0) SERV->htcd.running=0;
75 }
76 for(int i=0;i<SERVERS;i++) {
77 server[i]->term();
78 pthread_join(server[i]->ptid,0);
79 }
80 pthread_kill(crontab->tid,SIGHUP);
81 pthread_join(crontab->ptid,0);
82}
83
84///////////////////////////////////////////////////////////////
85
86static void httpServer(int overport)
87{
88 isocket sock(SERV->htcd.node.addr,overport,BACKLOG);
89 sock.keepalive(1);
90 sock.sendbufsize(SNDBUFSIZE);
91 sock.recvbufsize(RCVBUFSIZE);
92
93 sigignore(SIGPIPE);
94 disp_t onterm=signal(SIGTERM,onTERM);
95 disp_t onint=signal(SIGINT,onTERM);
96 disp_t onhup=signal(SIGHUP,onHUP);
97 MainProc(sock);
98 signal(SIGHUP,onhup);
99 signal(SIGINT,onint);
100 signal(SIGTERM,onterm);
101}
102
103static void Daemon(int overport) try
104{
105 PROCLOCK(PATH+PIDURI);
106 SERV=new htcServ(PATH);
107 crontab=new thrCron(*SERV);
108 pthread_create(&crontab->ptid,0,thr_cron,crontab);
109 for(int i=0;i<SERVERS;i++) {
110 server[i]=new thrServ(*SERV);
111 pthread_create(&server[i]->ptid,0,thr_handler,server[i]);
112 }
113 merr<<"htcd: "<<PATH<<" started\n";
114 httpServer(overport<0?0:overport==0?SERV->htcd.port:overport);
115 merr<<"htcd: "<<PATH<<" terminating\n";
116 for(int i=0;i<SERVERS;i++) delete server[i];
117 delete crontab;
118}
119catch(const merror_t& e) {
120 if(SERV) {
121 SERV->htcd.errlog<<"["<<time(0)<<"][MAIN]["<<e.desc<<"]\n";
122 merr<<e.desc<<"\n";
123 }
124 else if(First(e.desc)!=sref("proclock:")) merr<<e.desc<<"\n";
125}
126catch(...) {
127 if(SERV) SERV->htcd.errlog<<"["<<time(0)<<"][MAIN][FATAL]\n";
128 merr<<"FATAL\n";
129}
130
131main(int argc,char* argv[]) try
132{
133 if(argc<3) {
134 merr<<"Usage: "<<argv[0]<<" <path> <overport=-1|0|port> [-1|0|1]\n";
135 return -1;
136 }
137 PATH=argv[1]; if(PATH.back()=='/') PATH=PATH.popb();
138 setenv("DOCROOT",PATH.c_str(),1);
139 int overport=atoi(argv[2]);
140 int cmd=argc>3?atoi(argv[3]):0;
141 if(cmd) ProcTerminate(PATH+PIDURI);
142 if(cmd>=0) { if(fork()==0) Daemon(overport); }
143 delete SERV;
144 return 0;
145}
146catch(const merror_t& e) {
147 merr<<"ERROR: ["<<e.desc<<"]\n";
148 return -1;
149}
150catch(...) {
151 merr<<"ERROR: [FATAL]\n";
152 return -1;
153}
diff --git a/src/net/isocket.cc b/src/net/isocket.cc
new file mode 100644
index 0000000..af94189
--- /dev/null
+++ b/src/net/isocket.cc
@@ -0,0 +1,58 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/isocket.h>
21#include <errno.h>
22
23isocket::isocket(const in_addr& ia,int port,int backlog):
24 pipe_stream(-1),rd(-1)
25{
26 if(port) {
27 fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
28 if(fd<0) THROW("isocket: Could not create");
29 reuse(1);
30 }
31 else fd=0;
32 sa.sin_family=2;
33 sa.sin_port=htons(port);
34 sa.sin_addr=ia;
35 if(port) {
36 if(bind(fd,(sockaddr*)&sa,sizeof(sa))==-1) THROW("isocket: Could not bind");
37 }
38 if(listen(fd,backlog)==-1) THROW("isocket: Could not listen");
39 rd.setfd(fd);
40}
41
42isocket::isocket(int f,const sockaddr_in& ia):
43 pipe_stream(f),rd(f)
44{
45 sa=ia;
46 setflag(O_NONBLOCK|O_NDELAY);
47 nodelay(1);
48}
49
50isocket* isocket::accept() throw(merror_t)
51{
52 sockaddr_in tsa; socklen_t tsalen;
53 memset(&tsa,0,tsalen=sizeof(tsa));
54 int tfd=::accept(fd,(sockaddr*)&tsa,&tsalen);
55 if(tfd>0) return new isocket(tfd,tsa);
56 if(errno!=EAGAIN) THROW("isocket: could not accept");
57 return 0;
58}
diff --git a/src/net/isocket.h b/src/net/isocket.h
new file mode 100644
index 0000000..5ca1ec3
--- /dev/null
+++ b/src/net/isocket.h
@@ -0,0 +1,68 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef ISOCKETH
21#define ISOCKETH
22
23#include <mt/mread.h>
24#include <mt/mstring.h>
25#include <sys/socket.h>
26#include <arpa/inet.h>
27#include <netinet/in.h>
28#include <netinet/tcp.h>
29
30class isocket : public pipe_stream {
31public:
32 isocket(const in_addr& ia,int port,int backlog);
33 isocket(int f,const sockaddr_in& ia);
34 ~isocket() { close(); }
35
36 void close() { if(fd>=0) { ::close(fd); fd=-1; }}
37
38 int getfd() const { return fd; }
39 int family() const { return sa.sin_family; }
40 int port() const { return ntohs(sa.sin_port); }
41 in_addr address() const { return sa.sin_addr; }
42
43 void reuse(int ok) { set(SOL_SOCKET,SO_REUSEADDR,ok); }
44 void nodelay(int ok) { set(IPPROTO_TCP,TCP_NODELAY,ok); }
45 void keepalive(int ok) { set(SOL_SOCKET,SO_KEEPALIVE,ok); }
46 void sendbufsize(int s) { set(SOL_SOCKET,SO_SNDBUF,s); }
47 void recvbufsize(int s) { set(SOL_SOCKET,SO_RCVBUF,s); }
48
49 isocket* accept() throw(merror_t);
50
51 int test() { return rd.poll(); }
52 int getsome(char* s,int n) { return rd.read(s,n); }
53 int gethead(char* s,int n) { return rd.readpara(s,n); }
54 int getbody(char* s,int n) { return rd.readx(s,n); }
55
56protected:
57 void setflag(int f) { fcntl(fd,F_SETFL,f); }
58 int getflag() const { return fcntl(fd,F_GETFL,0); }
59 void set(int lev,int opt,int ok) throw(merror_t) {
60 if(setsockopt(fd,lev,opt,(char*)&ok,sizeof(ok))<0)
61 THROW("isocket: Could not set option");
62 }
63private:
64 sockaddr_in sa;
65 mread rd;
66};
67
68#endif
diff --git a/src/net/redirect.cc b/src/net/redirect.cc
new file mode 100644
index 0000000..7e07e7c
--- /dev/null
+++ b/src/net/redirect.cc
@@ -0,0 +1,185 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/isocket.h>
21#include <mail/res.h>
22#include <http/http.h>
23#include <mt/lookup.h>
24#include <mt/lock.h>
25#include <sys/utsname.h>
26#include <signal.h>
27
28static fp_stream merr(stderr);
29static IPnode NODE;
30static int PORT;
31static mstring URL,PATH,SERVER,URL1,URL2;
32static int volatile RUNNING;
33
34const mstring REDIRECT="/tmp/redirect.";
35const int BACKLOG=4;
36const int SNDBUFSIZE=16384;
37const int RCVBUFSIZE=16384;
38const int MAXHEAD=16384;
39const int SAFEZONE=4096;
40
41static void BreakURL()
42{
43 static const mstring pre="//";
44 int p=URL.find(pre);
45 if(p>=0) {
46 p+=pre.size();
47 int q=p+URL.right(p).find('/');
48 if(q>=p) {
49 URL1=URL.left(q);
50 URL2=URL.right(q);
51 }
52 else {
53 URL1=URL;
54 URL2.clear();
55 }
56 }
57 else throw(0);
58}
59
60static mstring Combine(const sref& uri)
61{
62 const int ncvt=3;
63 static const mstring cvt[ncvt]={"/BODY","/en","/sv"};
64 mstring d=uri;
65 mstring s=URL1;
66 for(int i=0;i<ncvt;i++) {
67 int p=d.find(cvt[i]);
68 if(p>=0) {
69 d.erase(p,cvt[i].size());
70 s+=cvt[i];
71 }
72 }
73 s+=URL2;
74 s+=d;
75 return s;
76}
77
78static int Handle(isocket& sock)
79{
80 mstring buffer(MAXHEAD+SAFEZONE);
81 int nhead=sock.gethead(buffer.data(),MAXHEAD);
82 if(nhead<=0) return 0;
83 httpReq req(sref(buffer.data(),nhead));
84 httpResp resp;
85 resp.status=HTTP_301;
86 //resp.location=URL+req.uri;
87 resp.location=Combine(req.uri);
88 if(req.arg.nempty()) { resp.location.append(1,'?'); resp.location+=req.arg; }
89 resp.putHead(sock);
90 putend(sock);
91 sock.close();
92 return 1;
93}
94
95///////////////////////////////////////////////////////////////
96
97extern "C" {
98 static void onTERM(int sig) { RUNNING=0; }
99 typedef void (*disp_t)(int);
100}
101
102static void MainProc(isocket& sock)
103{
104 RUNNING=1;
105 while(RUNNING) {
106 int test=sock.test();
107 if(test>0) {
108 try {
109 isocket* s=sock.accept();
110 if(s) Handle(*s);
111 }
112 catch(const merror_t& e) {
113 merr<<"SOCKET: "<<e.desc<<"\n";
114 }
115 }
116 else if(test<0) RUNNING=0;
117 }
118}
119
120///////////////////////////////////////////////////////////////
121
122static void httpServer()
123{
124 isocket sock(NODE.addr,PORT,BACKLOG);
125 sock.keepalive(1);
126 sock.sendbufsize(SNDBUFSIZE);
127 sock.recvbufsize(RCVBUFSIZE);
128 sigignore(SIGPIPE);
129 disp_t onterm=signal(SIGTERM,onTERM);
130 disp_t onint=signal(SIGINT,onTERM);
131 MainProc(sock);
132 signal(SIGINT,onint);
133 signal(SIGTERM,onterm);
134}
135
136static void Daemon() try
137{
138 PROCLOCK(PATH);
139 merr<<"redirect: "<<SERVER<<" -> "<<URL<<" started\n";
140 httpServer();
141}
142catch(const merror_t& e) {
143 if(First(e.desc)!=sref("proclock:")) merr<<e.desc<<"\n";
144}
145catch(...) {
146 merr<<"FATAL\n";
147}
148
149main(int argc,char* argv[]) try
150{
151 if(argc<3) {
152 merr<<"Usage: "<<argv[0]<<" [host:]<port> <url> [-1|0|1]\n";
153 return -1;
154 }
155 sref s(argv[1]);
156 mstring host=s.left_last(':');
157 mstring sport=s.past_last(':');
158 if(sport.empty()) {
159 sport=host;
160 host.clear();
161 }
162 PORT=atoi(sport);
163 URL=argv[2];
164 if(URL.back()=='/') URL=URL.popb();
165 BreakURL();
166 if(host.empty()) {
167 struct utsname u; uname(&u);
168 host=u.nodename;
169 }
170 Lookup(NODE,host);
171 SERVER=NODE.name; SERVER.append(1,'-'); SERVER+=itoa(PORT);
172 PATH=REDIRECT; PATH+=SERVER;
173 int cmd=argc>3?atoi(argv[3]):0;
174 if(cmd) ProcTerminate(PATH);
175 if(cmd>=0) { if(fork()==0) Daemon(); }
176 return 0;
177}
178catch(const merror_t& e) {
179 merr<<"ERROR: ["<<e.desc<<"]\n";
180 return -1;
181}
182catch(...) {
183 merr<<"ERROR: [FATAL]\n";
184 return -1;
185}
diff --git a/src/net/route80.cc b/src/net/route80.cc
new file mode 100644
index 0000000..e883aba
--- /dev/null
+++ b/src/net/route80.cc
@@ -0,0 +1,64 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/isocket.h>
21#include <mt/lookup.h>
22#include <sys/utsname.h>
23
24static fp_stream merr(stderr);
25static IPnode NODE;
26static mstring PATH;
27static int PORT;
28
29const int BACKLOG=4;
30const int SNDBUFSIZE=16384;
31const int RCVBUFSIZE=16384;
32
33///////////////////////////////////////////////////////////////
34
35static void MainProc(isocket& sock)
36{
37 int fd=dup2(sock.fd,0);
38 if(fd!=0) { merr<<"Not right\n"; return; }
39 execl("htcd","htcd",PATH.c_str(),"-1",0);
40}
41
42///////////////////////////////////////////////////////////////
43
44static void httpServer()
45{
46 isocket sock(NODE.addr,PORT,BACKLOG);
47 sock.keepalive(1);
48 sock.sendbufsize(SNDBUFSIZE);
49 sock.recvbufsize(RCVBUFSIZE);
50 MainProc(sock);
51}
52
53main(int argc,char* argv[])
54{
55 if(argc<3) { merr<<"Usage: "<<argv[0]<<" <path> <port>\n"; return -1; }
56 PATH=argv[1]; if(PATH.back()=='/') PATH=PATH.popb();
57 PORT=atoi(argv[2]);
58 struct utsname u; uname(&u);
59 Lookup(NODE,sref(u.nodename));
60 httpServer();
61 return 0;
62}
63
64
diff --git a/src/net/server.cc b/src/net/server.cc
new file mode 100644
index 0000000..6996b20
--- /dev/null
+++ b/src/net/server.cc
@@ -0,0 +1,75 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/server.h>
21
22const mstring SERVURI="/htc/server.htc";
23
24htcServ::htcServ(const sref& path) : htcd(path),user(htcd.toks)
25{
26 Setup(user,htcd);
27 LoadBuffer(server,path+SERVURI);
28}
29
30///////////////////////////////////////////////////////
31
32static void Log(fp_stream& tlog,htcd_req& R,const sref& status)
33{
34 MLOCK(R.htcd()->mutex);
35 tlog<<"["<<time(0)<<"]["<<R.tcp->node.ip<<"]["
36 <<R.tcp->node.name<<":"<<R.tcp->port<<"]["
37 <<R.group<<":"<<R.user.uid()<<"]["
38 <<First(status)<<"]["<<R.req->method<<"]["
39 <<R.req->uri<<"]["<<R.req->arg<<"]\n";
40 tlog.flush();
41}
42
43///////////////////////////////////////////////////////
44
45int SendStatus(isocket& out,htcd_req& R,int keep,const sref& status,const sref& msg)
46{
47 R.resp.status=status;
48 if(atof(R.req->version.past_first(http_ver))<http_major) R.resp.version=HTTP_V10;
49 if(keep) R.resp.connect=keep_tag;
50 if(R.resp.cont_enc.nempty()||
51 R.resp.trans_enc.nempty()||
52 R.resp.status==HTTP_100||
53 R.resp.status==HTTP_204||
54 R.resp.status==HTTP_304||
55 eqn(R.req->method,HTTP_HEAD)) {
56 R.resp.cont_type.clear();
57 R.resp.cont_length.clear();
58 }
59 else {
60 if(R.resp.cont_type.empty()) R.resp.cont_type=http_mime_default;
61 R.resp.cont_length=itoa(msg.size());
62 }
63 Log(R.htcd()->logger,R,status);
64 R.resp.putHead(out);
65 putend(out);
66 out<<msg;
67#if 0
68 static fp_stream merr(stderr);
69 merr<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n";
70 R.resp.putHead(merr);
71 putend(merr);
72 merr<<"=================================\n";
73#endif
74 return out.hup?0:keep;
75}
diff --git a/src/net/server.h b/src/net/server.h
new file mode 100644
index 0000000..65f884c
--- /dev/null
+++ b/src/net/server.h
@@ -0,0 +1,46 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef SERVERH
21#define SERVERH
22
23#include <serv/htcd.h>
24#include <hdb/buffer.h>
25#include <net/isocket.h>
26#include <mt/lock.h>
27#include <signal.h>
28
29const mstring http_ver="HTTP/";
30const double http_minor=1.0,http_major=1.1;
31
32const mstring keep_tag="Keep-Alive";
33const mstring close_tag="Close";
34const mstring expect_continue_tag="100-continue";
35
36struct htcServ {
37 HTCd htcd;
38 tokmap user;
39 mstring server;
40 htcServ(const sref& path);
41};
42
43int SendStatus(isocket& out,htcd_req& R,int keep,
44 const sref& status,const sref& msg=ms_empty);
45
46#endif
diff --git a/src/net/test.cc b/src/net/test.cc
new file mode 100644
index 0000000..c0e3b41
--- /dev/null
+++ b/src/net/test.cc
@@ -0,0 +1,44 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <mt/mlock.h>
21#include <iostream>
22using namespace std;
23
24static mutex_t mutex;
25static mtcond_t cond;
26
27static void* thread(void* a)
28{
29 cerr<<"thread "<<a<<endl;
30 MSUSPEND(mutex,cond);
31 return 0;
32}
33
34main()
35{
36 pthread_t tid;
37 pthread_create(&tid,0,thread,(void*)2);
38 cerr<<"main thread"<<endl;
39 sleep(2);
40 MCONTINUE(cond);
41 pthread_join(tid,0);
42 cerr<<"afer join"<<endl;
43 return 0;
44}
diff --git a/src/net/thrserv.cc b/src/net/thrserv.cc
new file mode 100644
index 0000000..0d91d12
--- /dev/null
+++ b/src/net/thrserv.cc
@@ -0,0 +1,255 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <net/thrserv.h>
21#include <errno.h>
22
23const mstring cron_tag="\\run.cron";
24const mstring FATAL="FATAL ERROR";
25const mstring UNKNOWN="UNKNOWN";
26const mstring REJECTED="REJECTED";
27
28const int MAXHEAD=16384;
29const int MAXBODY=2<<21;
30const int MAXURI=4096;
31const int MAXARG=4096;
32const int SAFEZONE=4096;
33
34///////////////////////////////////////////////////////////////
35
36thrServ::thrServ(htcServ& server):
37 pmutex(MUTEX_INIT),
38 pcond(MTCOND_INIT),
39 keepalive(0),running(0),termok(0),
40 first(time(0)),last(time(0)),
41 serv(&server),
42 sock(0),
43 user(server.user,server.htcd.docroot)
44{
45}
46
47thrServ::~thrServ()
48{
49 delete sock;
50}
51
52void thrServ::reset(isocket* s,int keep)
53{
54 keepalive=keep;
55 running=1;
56 termok=0;
57 first=time(0);
58 last=time(0);
59 sock=s;
60 while(!tid);
61 if(MCONTINUE(pcond)) throw((int)0);
62}
63
64void thrServ::Log(const sref& msg)
65{
66 MLOCK(serv->htcd.mutex);
67 if(sock) serv->htcd.errlog<<"["<<time(0)<<"]["<<tid<<"]["
68 <<inet_ntoa(sock->address())<<":"<<sock->port()<<"]["
69 <<msg<<"]\n";
70 else serv->htcd.errlog<<"["<<time(0)<<"]["<<tid<<"]["<<msg<<"]\n";
71 serv->htcd.errlog.flush();
72}
73
74void thrServ::enter()
75{
76 tid=pthread_self();
77 MSUSPEND(pmutex,pcond)
78 while(serv->htcd.running&&!termok) {
79 session();
80 delete sock;
81 sock=0;
82 if(serv->htcd.running&&!termok) {
83 MSUSPEND(pmutex,pcond)
84 }
85 }
86}
87
88void thrServ::session() try
89{
90 int keep=1;
91 while(sock&&keep&&running) {
92 int test=sock->test();
93 if(test>0) { last=time(0); keep=handle(); }
94 else if(test<0) keep=0;
95 }
96}
97catch(const merror_t& e) {
98 Log(e.desc);
99}
100catch(...) {
101 Log(FATAL);
102}
103
104///////////////////////////////////////////////////////////////
105
106thrCron::thrCron(htcServ& server):
107 tid(0),running(0),serv(&server),user(server.user,server.htcd.docroot)
108{
109}
110
111void thrCron::Log(const sref& msg)
112{
113 MLOCK(serv->htcd.mutex);
114 serv->htcd.errlog<<"["<<time(0)<<"][CRON]["<<msg<<"]\n";
115 serv->htcd.errlog.flush();
116}
117
118void thrCron::enter() try
119{
120 tid=pthread_self();
121 tcpReq tcp; tcp.port=0;
122 httpReq req;
123 mstream devnull;
124 htcd_req R(serv->htcd,user.toks,devnull,tcp,req);
125 Env env(serv->htcd.ops,R,XSYSTEM);
126 env.req->running=&running;
127 running=1;
128 mstream m;
129 env.parse(m,cron_tag);
130}
131catch(const merror_t& e) {
132 Log(e.desc);
133}
134catch(...) {
135 Log(FATAL);
136}
137
138
139///////////////////////////////////////////////////////////////
140
141int thrServ::handle()
142{
143 tcpReq tcp;
144 tcp.port=sock->port();
145 if(!Lookup(tcp.node,sock->address())) {
146 Log(REJECTED);
147 return 0;
148 }
149
150 //////////////////////////////////////////////////////////////////
151
152 mstring buffer(MAXHEAD+MAXBODY+SAFEZONE);
153 int nhead=sock->gethead(buffer.data(),MAXHEAD);
154 if(nhead==0) return 0;
155 else if(nhead<0) return 0;
156
157 sref message(buffer.data(),nhead);
158
159#if 0
160 static fp_stream merr(stderr);
161 merr<<"QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ\n";
162 merr<<message<<"\n";
163 merr<<"=====================================\n";
164#endif
165
166 httpReq req(message);
167
168 //////////////////////////////////////////////////////////////////
169
170 int keep=keepalive;
171 if(!eqn(req.connect,keep_tag)) keep=0;
172
173 mswrite cache;
174 htcd_req R(serv->htcd,user.toks,cache,tcp,req);
175
176 //////////////////////////////////////////////////////////////////
177
178 if(nhead>=MAXHEAD) return SendStatus(*sock,R,keep,HTTP_413);
179
180 if(eqn(req.method,HTTP_TRACE)) {
181 R.resp.cont_type="message/http";
182 return SendStatus(*sock,R,keep,HTTP_200,buffer.left(nhead));
183 }
184
185 if(req.expect.nempty()) {
186 if(eqn(req.expect,expect_continue_tag)) SendStatus(*sock,R,keep,HTTP_100);
187 else return SendStatus(*sock,R,keep,HTTP_417);
188 }
189
190 if(req.trans_enc.nempty()||req.cont_enc.nempty()) return SendStatus(*sock,R,0,HTTP_501);
191
192 //////////////////////////////////////////////////////////////////
193
194 int ilength=atoi(req.cont_length);
195 if(ilength>MAXBODY) return SendStatus(*sock,R,0,HTTP_413);
196 else if(ilength>0) {
197 int nbody=sock->getbody(buffer.data()+nhead,ilength);
198 if(nbody<0) return 0;
199 else {
200 sref sbody(buffer.data()+nhead,nbody);
201#if 0
202 static fp_stream merr(stderr);
203 merr<<"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP\n";
204 merr<<sbody<<"\n";
205 merr<<"=====================================\n";
206#endif
207 R.AddBody(sbody);
208 if(req.body.size()!=ilength) return 0;
209 }
210 }
211
212 //////////////////////////////////////////////////////////////////
213
214 if(eqn(req.method,HTTP_OPTIONS)) {
215 R.resp.allow="HEAD GET PUT POST DELETE";
216 return SendStatus(*sock,R,keep,HTTP_200);
217 }
218
219 //////////////////////////////////////////////////////////////////
220
221 if(req.cont_length.empty()&&(eqn(req.method,HTTP_PUT)||eqn(req.method,HTTP_POST)))
222 return SendStatus(*sock,R,0,HTTP_411);
223
224 if(eqn(req.method,HTTP_HEAD)||
225 eqn(req.method,HTTP_GET)||
226 eqn(req.method,HTTP_PUT)||
227 eqn(req.method,HTTP_DELETE)||
228 eqn(req.method,HTTP_POST)) {
229 R.resp.cont_type=mime_texthtml;
230 R.resp.cont_type_charset=mime_default;
231 try {
232 Env env(serv->htcd.ops,R,XSYSTEM);
233 env.req->running=&running;
234 mstream m;
235 env.parse(m,serv->server);
236 if(!env.req->is_running()) THROW("htc: "<<req.uri<<" ended prematurely; reload");
237 }
238 catch(const merror_t& e) {
239 Log(e.desc);
240 return SendStatus(*sock,R,0,HTTP_503,e.desc);
241 }
242 }
243 else return SendStatus(*sock,R,keep,HTTP_501);
244
245 if(!keepalive) keep=0;
246 if(req.if_mod.nempty()&&R.resp.lastmod.nempty()) {
247 time_t since=cvtTime(req.if_mod),lst=cvtTime(R.resp.lastmod);
248 if(lst<=since) return SendStatus(*sock,R,keep,HTTP_304);
249 }
250
251 mstring status=R.resp.status;
252 if(eqn(req.method,HTTP_HEAD)) return SendStatus(*sock,R,keep,status);
253 else return SendStatus(*sock,R,keep,status,cache.str());
254
255}
diff --git a/src/net/thrserv.h b/src/net/thrserv.h
new file mode 100644
index 0000000..09307f6
--- /dev/null
+++ b/src/net/thrserv.h
@@ -0,0 +1,79 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef THRSERVH
21#define THRSERVH
22
23#include <net/server.h>
24#include <mt/lookup.h>
25#include <mt/mlock.h>
26
27////////////////////////////////////////////////////////
28//
29// MT - safe
30// Note that mutexes aren't needed here, since control
31// is flowing from main to child, with possible child
32// override in local variables.
33
34struct thrServ {
35 pthread_t ptid;
36 mutex_t pmutex;
37 mtcond_t pcond;
38 volatile int tid,keepalive,running,termok;
39 time_t first,last;
40 htcServ* serv;
41 isocket* sock;
42 htcd_user user;
43
44 thrServ(htcServ& server);
45 ~thrServ();
46
47 void Log(const sref& msg);
48 void reset(isocket* s,int keep);
49
50 int vacant() const { return sock==0; }
51 int shutdown() { keepalive=0; return sock==0; }
52 void disconnect() { keepalive=0; running=0; }
53 void term() {
54 keepalive=0;
55 running=0;
56 termok=1;
57 MCONTINUE(pcond);
58 }
59
60 void enter();
61 void session();
62 int handle();
63};
64
65////////////////////////////////////////////////////////
66
67struct thrCron {
68 pthread_t ptid;
69 volatile int tid,running;
70 htcServ* serv;
71 htcd_user user;
72
73 thrCron(htcServ& server);
74
75 void Log(const sref& msg);
76 void enter();
77};
78
79#endif
diff --git a/src/ops/basic.cc b/src/ops/basic.cc
new file mode 100644
index 0000000..b30e351
--- /dev/null
+++ b/src/ops/basic.cc
@@ -0,0 +1,269 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/operator.h>
21#include <math.h>
22
23OP1_IMPL(exp) { out<<exp(atof(a)); }
24OP1_IMPL(ln) { out<<log(atof(a)); }
25OP1_IMPL(abs) { out<<fabs(atof(a)); }
26OP1_IMPL(int) { out<<int(atof(a)); }
27
28OP1_IMPL(minus) { out<<-atof(a); }
29OP2_IMPL(minus) { out<<atof(L)-atof(R); }
30OP1_IMPL(plus) { out<<atof(a); }
31OP2_IMPL(plus) { out<<atof(L)+atof(R); }
32OP2_IMPL(mul) { out<<atof(L)*atof(R); }
33OP2_IMPL(divide) { out<<atof(L)/atof(R); }
34OP2_IMPL(mod) {
35 double a=atof(L),b=atof(R);
36 a-=b*int(a/b);
37 if(a<0) a+=fabs(b);
38 out<<a;
39}
40OP2_IMPL(imod) { out<<(atoi(L)%atoi(R)); }
41OP2_IMPL(div) { out<<(atoi(L)/atoi(R)); }
42OP2_IMPL(pow) { out<<pow(atof(L),atof(R)); }
43
44OP2_IMPL(eq) {out<<(L==R); }
45OP2_IMPL(ne) {out<<(L!=R);}
46OP2_IMPL(eqn) {out<<(L.compare(R,cset_lcase)==0);}
47OP2_IMPL(nen) {out<<(L.compare(R,cset_lcase)!=0);}
48OP2_IMPL(eqf) {out<<(atof(L)==atof(R));}
49OP2_IMPL(nef) {out<<(atof(L)!=atof(R));}
50
51OP1_IMPL(not) {out<<!atob(a);}
52OP2_IMPL(and) {out<<(atob(L)&atob(R)); }
53OP2_IMPL(or) {out<<(atob(L)|atob(R)); }
54OP2_IMPL(xor) {out<<(atob(L)^atob(R)); }
55
56OP2_IMPL(shiftleft) {out<<(atoi(L)<<atoi(R));}
57OP2_IMPL(shiftright) {out<<(atoi(L)>>atoi(R));}
58
59OP1_IMPL(bitnot) {out<<~atoi(a);}
60OP2_IMPL(bitand) {out<<(atoi(L)&atoi(R)); }
61OP2_IMPL(bitor) {out<<(atoi(L)|atoi(R)); }
62OP2_IMPL(bitxor) {out<<(atoi(L)^atoi(R)); }
63
64OP2_IMPL(SP) {out<<L<<" "<<R;}
65
66OP2_IMPL(comma) {out<<R;}
67
68OP1_IMPL(semi) {}
69OP2_IMPL(semi) {}
70
71void opAddBasic(opmap& M)
72{
73 OP_ADD(32,exp,
74 "C style\n"
75 "Natural exponential function\n"
76 "Syntax: exp (real)\n"
77 "Returns: (real)\n"
78 );
79 OP_ADD(32,ln,
80 "C style\n"
81 "Natural logarithm function\n"
82 "Syntax: ln (real)\n"
83 "Returns: (real)\n"
84 );
85 OP_ADD(32,abs,
86 "C style\n"
87 "Absolute value\n"
88 "Syntax: abs (real)\n"
89 "Returns: (real)\n"
90 );
91 OP_ADD(32,int,
92 "C style\n"
93 "Integer truncation\n"
94 "Syntax: int (real)\n"
95 "Returns: (int)\n"
96 "\n"
97 "Note that truncation is just as when converting to int, not rounding\n"
98 );
99
100 OP_ADDN(30,bitnot,~,
101 "C style\n"
102 "Bitwise NOT\n"
103 "Syntax: ~ (int)\n"
104 "Returns: (int)\n"
105 );
106 OP_ADDN(30,not,!,
107 "C style\n"
108 "Logical NOT\n"
109 "Syntax: ! (int)\n"
110 "Returns: (int)\n"
111 );
112 OP_ADD2(30,24,plus,+,
113 "C style\n"
114 "Addition\n"
115 "Syntax: (real) + (real)\n"
116 "Returns: (real)\n"
117 );
118 OP_ADD2(30,24,minus,-,
119 "C style\n"
120 "Subtraction\n"
121 "Syntax: (real) - (real)\n"
122 "Returns: (real)\n"
123 );
124
125 OP_ADDN(27,pow,**,
126 "Power\n"
127 "Syntax: (real) a ** (real) b\n"
128 "Returns: (real) a to the power of b\n"
129 );
130
131 OP_ADDN(26,mul,*,
132 "C style\n"
133 "Multiplication\n"
134 "Syntax: (real) * (real)\n"
135 "Returns: (real)\n"
136 );
137 OP_ADDN(26,divide,/,
138 "C style\n"
139 "Division\n"
140 "Syntax: (real) / (real)\n"
141 "Returns: (real)\n"
142 "\n"
143 "Note computerese; same precedence as *\n"
144 );
145 OP_ADDN(26,imod,%,
146 "C style\n"
147 "Integer modulus\n"
148 "Syntax: (int) % (int)\n"
149 "Returns: (int)\n"
150 );
151
152 OP_ADD(25,div,
153 "Integer division\n"
154 "Syntax: (int) div (int)\n"
155 "Returns: (int)\n"
156 "\n"
157 "Note that this is the same as integer / in C, but with lower precedence\n"
158 );
159 // plus/minus 24
160 OP_ADD(23,mod,
161 "General moulus\n"
162 "Syntax: (real) mod (real)\n"
163 "Returns: (real)\n"
164 "\n"
165 "Modulus on ring; negative vals are mapped onto base\n"
166 );
167
168 OP_ADDN(22,shiftleft,<<,
169 "C style\n"
170 "Shift left\n"
171 "Syntax: (int) << (int)\n"
172 "Returns: (int)\n"
173 );
174 OP_ADDN(22,shiftright,>>,
175 "C style\n"
176 "Shift right\n"
177 "Syntax: (int) >> (int)\n"
178 "Returns: (int)\n"
179 );
180
181 OP_ADD(18,eq,
182 "Lexicographic equal\n"
183 "Syntax: (string) eq (string)\n"
184 "Returns: (int)\n"
185 );
186 OP_ADD(18,eqn,
187 "Lexicographic equal, case insensitive\n"
188 "Syntax: (string) eqn (string)\n"
189 "Returns: (int)\n"
190 );
191 OP_ADDN(18,eqf,==,
192 "Arithmetic equal\n"
193 "Syntax: (real) == (real)\n"
194 "Returns: (int)\n"
195 );
196 OP_ADD(18,ne,
197 "Lexicographic not equal\n"
198 "Syntax: (string) ne (string)\n"
199 "Returns: (int)\n"
200 );
201 OP_ADD(18,nen,
202 "Lexicographic not equal, case insensitive\n"
203 "Syntax: (string) nen (string)\n"
204 "Returns: (int)\n"
205 );
206 OP_ADDN(18,nef,!=,
207 "Arithmetic not equal\n"
208 "Syntax: (real) != (real)\n"
209 "Returns: (int)\n"
210 );
211
212 OP_ADDN(16,bitand,&,
213 "C style\n"
214 "Bitwise AND\n"
215 "Syntax: (int) & (int)\n"
216 "Returns: (int)\n"
217 );
218 OP_ADDN(14,bitxor,^,
219 "C style\n"
220 "Bitwise XOR\n"
221 "Syntax: (int) ^ (int)\n"
222 "Returns: (int)\n"
223 );
224 OP_ADDN(12,bitor,|,
225 "C style\n"
226 "Bitwise OR\n"
227 "Syntax: (int) | (int)\n"
228 "Returns: (int)\n"
229 );
230
231 OP_ADDN(10,and,&&,
232 "C style\n"
233 "Logical AND\n"
234 "Syntax: (int) && (int)\n"
235 "Returns: (int)\n"
236 );
237 OP_ADDN(9,xor,^^,
238 "Logical XOR\n"
239 "Syntax: (int) ^^ (int)\n"
240 "Returns: (int)\n"
241 );
242 OP_ADDN(8,or,||,
243 "C style\n"
244 "Logical OR\n"
245 "Syntax: (int) || (int)\n"
246 "Returns: (int)\n"
247 );
248
249 /*
250 OP_ADD(3,SP,
251 "Whitespace padding\n"
252 "Syntax: a ws OR ws a OR a ws b\n"
253 "Returns: a b\n"
254 );
255 */
256
257 M.add(new op_t(",",2,impl_comma,
258 "C style\n"
259 "Separate expression\n"
260 "Syntax: a , b\n"
261 "Returns: b\n"
262 ));
263 OP_ADD2(1,1,semi,;,
264 "C style\n"
265 "End expression\n"
266 "Syntax: a ; OR a ; b\n"
267 "Returns: nothing\n"
268 );
269}
diff --git a/src/ops/comp.cc b/src/ops/comp.cc
new file mode 100644
index 0000000..aa40246
--- /dev/null
+++ b/src/ops/comp.cc
@@ -0,0 +1,134 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/operator.h>
21#include <ops/nnstyle.h>
22
23OP2_IMPL(lt) {out<<(L<R);}
24OP2_IMPL(le) {out<<(L<=R);}
25OP2_IMPL(ge) {out<<(L>=R);}
26OP2_IMPL(gt) {out<<(L>R);}
27OP2_IMPL(ltn) {out<<(L.compare(R,cset_lcase)<0);}
28OP2_IMPL(len) {out<<(L.compare(R,cset_lcase)<=0);}
29OP2_IMPL(gen) {out<<(L.compare(R,cset_lcase)>=0);}
30OP2_IMPL(gtn) {out<<(L.compare(R,cset_lcase)>0);}
31OP2_IMPL(ltnn) {out<<(nncomp(L,R)<0);}
32OP2_IMPL(lenn) {out<<(nncomp(L,R)<=0);}
33OP2_IMPL(genn) {out<<(nncomp(L,R)>=0);}
34OP2_IMPL(gtnn) {out<<(nncomp(L,R)>0);}
35OP2_IMPL(ltf) {out<<(atof(L)<atof(R));}
36OP2_IMPL(lef) {out<<(atof(L)<=atof(R));}
37OP2_IMPL(gef) {out<<(atof(L)>=atof(R));}
38OP2_IMPL(gtf) {out<<(atof(L)>atof(R));}
39
40void opAddComp(opmap& M)
41{
42 OP_ADD(20,lt,
43 "Lexicographic less than\n"
44 "Syntax: (string) lt (string)\n"
45 "Returns: (int)\n"
46 );
47 OP_ADD(20,le,
48 "Lexicographic less or equal\n"
49 "Syntax: (string) le (string)\n"
50 "Returns: (int)\n"
51 );
52 OP_ADD(20,ge,
53 "Lexicographic greater or equal\n"
54 "Syntax: (string) ge (string)\n"
55 "Returns: (int)\n"
56 );
57 OP_ADD(20,gt,
58 "Lexicographic greater than\n"
59 "Syntax: (string) gt (string)\n"
60 "Returns: (int)\n"
61 );
62
63 OP_ADD(20,ltn,
64 "Lexicographic less than, case insensitive\n"
65 "Syntax: (string) ltn (string)\n"
66 "Returns: (int)\n"
67 );
68 OP_ADD(20,len,
69 "Lexicographic less or equal, case insensitive\n"
70 "Syntax: (string) len (string)\n"
71 "Returns: (int)\n"
72 );
73 OP_ADD(20,gen,
74 "Lexicographic greater or equal, case insensitive\n"
75 "Syntax: (string) gen (string)\n"
76 "Returns: (int)\n"
77 );
78 OP_ADD(20,gtn,
79 "Lexicographic greater than, case insensitive\n"
80 "Syntax: (string) gtn (string)\n"
81 "Returns: (int)\n"
82 );
83
84 OP_ADD(20,ltnn,
85 "Lexicographic less than, NN-style\n"
86 "Syntax: (string) ltnn (string)\n"
87 "Returns: (int)\n"
88 "\n"
89 "NN-style compares names as <lastname> <initials>\n"
90 );
91 OP_ADD(20,lenn,
92 "Lexicographic less or equal, NN-style\n"
93 "Syntax: (string) lenn (string)\n"
94 "Returns: (int)\n"
95 "\n"
96 "NN-style compares names as <lastname> <initials>\n"
97 );
98 OP_ADD(20,genn,
99 "Lexicographic greater or equal, NN-style\n"
100 "Syntax: (string) genn (string)\n"
101 "Returns: (int)\n"
102 "\n"
103 "NN-style compares names as <lastname> <initials>\n"
104 );
105 OP_ADD(20,gtnn,
106 "Lexicographic greater than, NN-style\n"
107 "Syntax: (string) gtnn (string)\n"
108 "Returns: (int)\n"
109 "\n"
110 "NN-style compares names as <lastname> <initials>\n"
111 );
112
113 OP_ADDN(20,ltf,<,
114 "Arithmetic less than\n"
115 "Syntax: (real) < (real)\n"
116 "Returns: (int)\n"
117 );
118 OP_ADDN(20,lef,<=,
119 "Arithmetic less or equal\n"
120 "Syntax: (real) <= (real)\n"
121 "Returns: (int)\n"
122 );
123 OP_ADDN(20,gef,>=,
124 "Arithmetic greater or equal\n"
125 "Syntax: (real) >= (real)\n"
126 "Returns: (int)\n"
127 );
128 OP_ADDN(20,gtf,>,
129 "Arithmetic greater than\n"
130 "Syntax: (real) > (real)\n"
131 "Returns: (int)\n"
132 );
133
134}
diff --git a/src/ops/express.cc b/src/ops/express.cc
new file mode 100644
index 0000000..2cd3114
--- /dev/null
+++ b/src/ops/express.cc
@@ -0,0 +1,173 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/express.h>
21
22const mstring sp_tag="SP";
23
24////////////////////////////////////////////////////////////////
25
26uniheap<sizeof(expr_t)> expr_t::tree;
27void* expr_t::operator new(size_t n) { return tree.push(); }
28void expr_t::operator delete(void* p) { tree.pop(p); }
29
30////////////////////////////////////////////////////////////////
31
32inline int precedence(const expr_t* root,const op_t* op)
33{
34 if(!root->op) return 1;
35 else if(!op) return 0;
36 else if(root->left) {
37 if(root->right) return op->pre2&&root->op->pre2>=op->pre2;
38 else return root->op->pre2>=op->pre1;
39 }
40 else {
41 if(root->right) return op->pre2&&root->op->pre1>=op->pre2;
42 else return root->op->pre1>=op->pre1;
43 }
44}
45
46static int ins_node_sp(expr_t*& root,op_env& env,
47 const sref& in,const op_t* op) throw(merror_t)
48{
49 if(root==0) { root=new expr_t(in,op); root->expand(env); return 1; }
50 else if(precedence(root,op)) {
51 if(op) { root=new expr_t(in,op,root); return 1; } else return 0;
52 }
53 else return ins_node_sp(root->right,env,in,op);
54}
55
56static void ins_node(expr_t*& root,op_env& env,const sref& in) throw(merror_t)
57{
58 const op_t* op=env.ops->get(in);
59 if(!ins_node_sp(root,env,in,op)) {
60 if(!ins_node_sp(root,env,sp_tag,env.ops->get(sp_tag)))
61 THROW("ops: ("<<root->expr<<" ["<<in<<"]): operator expected");
62 ins_node_sp(root,env,in,op);
63 }
64}
65
66///////////////////////////////////////////////////////////////
67
68void expr_t::clear()
69{
70 expr.clear();
71 op=0;
72 status=OP_ALL;
73 result.clear();
74 delete left; left=0;
75 delete right; right=0;
76}
77
78void expr_t::copy(const expr_t& x)
79{
80 expr=x.expr;
81 op=x.op;
82 if(x.left) left=new expr_t(*x.left);
83 if(x.right) right=new expr_t(*x.right);
84}
85
86void expr_t::trav(mstream& out,int n)
87{
88 if(n&&left) left->trav(out,n-1);
89 for(int i=0;i<3*n;i++) out.put(' ');
90 out<<"["<<expr<<"]("<<status<<") -> "<<result<<"\n";
91 if(n&&right) right->trav(out,n-1);
92}
93
94void expr_t::expand(op_env& env) throw(merror_t)
95{
96 if(!op) {
97 sref first,rest=expr;
98 env.split(first,rest);
99 if(first!=expr) {
100 do ins_node(right,env,first);
101 while(env.split(first,rest));
102 }
103 }
104}
105
106///////////////////////////////////////////////////////////////
107
108void expr_t::eval(mstream& out,op_env& env,int opt) throw(merror_t)
109{
110 if(op) {
111 if(left) {
112 if(op->left>1) {
113 if(left->status&opt) {
114 swrite sw(left->result);
115 left->eval(sw,env,opt);
116 }
117 }
118 else if(!op->left)
119 THROW("ops: ("<<left->expr<<" ["<<expr<<"]): not an L operator")
120 else if(left->op)
121 THROW("ops: (["<<left->expr<<"] "<<expr<<"): Lvalue required")
122 else {
123 left->status=OP_LOCAL;
124 left->result=left->expr;
125 }
126 }
127 if(right) {
128 if(op->right>1) {
129 if(right->status&opt) {
130 swrite sw(right->result);
131 right->eval(sw,env,opt);
132 }
133 }
134 else if(!op->right)
135 THROW("ops: ("<<right->expr<<" ["<<expr<<"]): not an R operator")
136 else if(right->op)
137 THROW("ops: (["<<right->expr<<"] "<<expr<<"): Lvalue required")
138 else {
139 right->status=OP_LOCAL;
140 right->result=right->expr;
141 }
142 }
143 if(left) {
144 if(right) {
145 status=left->status|right->status;
146 if((status&OP_NINIT)==0) op->f2(out,env,left->result,right->result);
147 }
148 else if(!op->f1)
149 THROW("ops: ("<<left->expr<<" "<<expr<<" [R]): missing R argument")
150 else {
151 status=left->status;
152 if((status&OP_NINIT)==0) op->f1(out,env,left->result);
153 }
154 }
155 else if(right) {
156 if(!op->f1)
157 THROW("ops: ([L] "<<expr<<" "<<right->expr<<"): missing L argument")
158 else {
159 status=right->status;
160 if((status&OP_NINIT)==0) op->f1(out,env,right->result);
161 }
162 }
163 else THROW("ops: ["<<expr<<"]: operator not expected");
164 }
165 else {
166 if(right) {
167 right->eval(out,env,opt);
168 status=right->status;
169 }
170 else env.term(out,this);
171 }
172 if(status&OP_NINIT) THROW("ops: unfinished expression ["<<expr<<"]");
173}
diff --git a/src/ops/express.h b/src/ops/express.h
new file mode 100644
index 0000000..79148f6
--- /dev/null
+++ b/src/ops/express.h
@@ -0,0 +1,79 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef EXPRESSH
21#define EXPRESSH
22
23#include <ops/operator.h>
24#include <mt/split.h>
25#include <mt/uniheap.h>
26
27const int OP_LOCAL=1;
28const int OP_GLOBAL=2;
29const int OP_NINIT=4;
30const int OP_ALL=OP_LOCAL|OP_GLOBAL|OP_NINIT;
31
32class expr_t {
33public:
34 sref expr;
35 const op_t* op;
36 int status;
37 mstring result;
38 expr_t *left,*right;
39
40 expr_t():
41 expr(),op(0),status(OP_ALL),result(),left(0),right(0) {}
42 expr_t(const expr_t& x):
43 expr(),op(0),status(OP_ALL),result(),left(0),right(0) { copy(x); }
44 expr_t(const sref& s):
45 expr(s),op(0),status(OP_ALL),result(),left(0),right(0) {}
46 expr_t(const sref& s,const op_t* o):
47 expr(s),op(o),status(OP_ALL),result(),left(0),right(0) {}
48 expr_t(const sref& s,const op_t* o,expr_t* p):
49 expr(s),op(o),status(OP_ALL),result(),left(p),right(0) {}
50 ~expr_t() { delete left; delete right; }
51
52 void clear();
53 expr_t& operator=(const expr_t& x) { clear(); copy(x); return *this; }
54 expr_t& operator=(const sref& in) { clear(); expr=in; return *this; }
55
56 void trav(mstream& out,int n);
57 void expand(op_env& env) throw(merror_t);
58 void eval(mstream& out,op_env& env,int opt) throw(merror_t);
59
60 static void* operator new(size_t n);
61 static void operator delete(void* p);
62protected:
63 void copy(const expr_t& x);
64 static uniheap<36> tree;
65};
66
67////////////////////////////////////////////////////////////
68
69struct op_env {
70 opmap* ops;
71
72 op_env() : ops(0) {}
73 op_env(opmap& map) : ops(&map) {}
74
75 virtual int split(sref& first,sref& rest) throw(merror_t) { return 0; }
76 virtual void term(mstream& out,expr_t* x) throw(merror_t) { x->status=0; }
77};
78
79#endif
diff --git a/src/ops/latex.cc b/src/ops/latex.cc
new file mode 100644
index 0000000..01ccfc0
--- /dev/null
+++ b/src/ops/latex.cc
@@ -0,0 +1,101 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/express.h>
21#include <math.h>
22
23OP1_IMPL(minus) {out<<"-"<<a;}
24OP1_IMPL(plus) {out<<"+"<<a;}
25OP1_IMPL(plusminus) {out<<"\\pm"<<a;}
26OP1_IMPL(minusplus) {out<<"\\mp"<<a;}
27
28OP2_IMPL(minus) {out<<L<<"-"<<R;}
29OP2_IMPL(plus) {out<<L<<"+"<<R;}
30OP2_IMPL(plusminus) {out<<L<<"\\pm"<<R;}
31OP2_IMPL(minusplus) {out<<L<<"\\mp"<<R;}
32
33OP2_IMPL(mul) {out<<L<<"\times"<<R;}
34OP2_IMPL(divide) {out<<L<<"/"<<R;}
35OP2_IMPL(pow) {out<<L<<"<sup><font size=-1>"<<R<<"</font></sup>";}
36OP1_IMPL(pow) {out<<"<sup><font size=-1>"<<a<<"</font></sup>";}
37OP2_IMPL(sub) {out<<L<<"<sub><font size=-1>"<<R<<"</font></sub>";}
38OP1_IMPL(sub) {out<<"<sub><font size=-1>"<<a<<"</font></sub>";}
39OP2_IMPL(div) {out<<L<<"\\div"<<R;}
40
41OP2_IMPL(lt) {out<<L<<"<"<<R;}
42OP2_IMPL(le) {out<<L<<"\\leq"<<R;}
43OP2_IMPL(eq) {out<<L<<"="<<R;}
44OP2_IMPL(ne) {out<<L<<"\\neq"<<R;}
45OP2_IMPL(ge) {out<<L<<"\\geq"<<R;}
46OP2_IMPL(gt) {out<<L<<">"<<R;}
47
48OP2_IMPL(equiv) {out<<L<<"\\equiv"<<R;}
49OP2_IMPL(sim) {out<<L<<"\\sim"<<R;}
50OP2_IMPL(simeq) {out<<L<<"\\simeq"<<R;}
51
52OP1_IMPL(not) {out<<"!"<<a;}
53OP2_IMPL(and) {out<<L<<" and "<<R;}
54OP2_IMPL(or) {out<<L<<" or "<<R;}
55OP2_IMPL(xor) {out<<L<<" xor "<<R;}
56
57OP2_IMPL(assign) {out<<L<<" = "<<R;}
58
59OP2_IMPL(SP) {out<<L<<" "<<R;}
60
61OP1_IMPL(semi) {out<<a;}
62OP2_IMPL(semi) {out<<L<<R;}
63
64void opAddLatex(opmap& M)
65{
66 OP_ADD(30,not,"logic not");
67
68 OP_ADD2(30,28,sub,_,"sub index");
69 OP_ADD2(30,27,pow,^,"raised index");
70
71 OP_ADD2(30,24,plus,+,"plus");
72 OP_ADD2(30,24,minus,-,"minus");
73 OP_ADD2(30,24,plusminus,+-,"plusminus");
74 OP_ADD2(30,24,minusplus,-+,"minusplus");
75
76 OP_ADDN(26,mul,*,"multiply");
77 OP_ADDN(25,divide,/,"divide");
78 OP_ADD(25,div,"divide-sign");
79 // plus/minus 24
80
81 OP_ADDN(20,lt,<,"less than");
82 OP_ADDN(20,le,<=,"less or equal");
83 OP_ADDN(20,ge,>=,"greater or equal");
84 OP_ADDN(20,gt,>,"greater than");
85
86 OP_ADDN(18,eq,==,"equal");
87 OP_ADDN(18,ne,!=,"not equal");
88 OP_ADDN(18,equiv,===,"equivalent");
89 OP_ADDN(18,sim,~,"similar");
90 OP_ADDN(18,simeq,~=,"similar equal");
91
92 OP_ADD(10,and,"logic and");
93 OP_ADD(9,xor,"logic xor");
94 OP_ADD(8,or,"logic or");
95
96 OP_ADDN(4,assign,=,"assignment");
97
98 OP_ADD(3,SP,"Whitespace padding");
99
100 OP_ADD2(1,1,semi,;,"concatenation");
101}
diff --git a/src/ops/nnstyle.h b/src/ops/nnstyle.h
new file mode 100644
index 0000000..4b8be5e
--- /dev/null
+++ b/src/ops/nnstyle.h
@@ -0,0 +1,53 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef NNSTYLEH
21#define NNSTYLEH
22
23#include <mt/split.h>
24
25const charset cset_wsdot=cset_ws|'.';
26
27inline mstring nncase(const sref& b)
28{
29 static const mstring comma_tag(","),and_tag("and");
30 mstring acc,a,name;
31 sref next,first,rest=b;
32 while(Split(first,rest,cset_wsdot)) {
33 if(first==comma_tag||eqn(first,and_tag)) continue;
34 (name=first.left_first(comma_tag)).tosim();
35 name[0]=cset_ucase[name[0]];
36 next=First(rest);
37 if(first.back()==','||next.empty()||*next==','||eqn(next,and_tag)) {
38 a.insert(0,name);
39 if(acc.nempty()) { acc+=' '; acc+=and_tag; acc+=' '; }
40 acc+=a;
41 a.clear();
42 }
43 else { a+=' '; a+=name[0]; a+='.'; }
44 }
45 return acc;
46}
47
48inline int nncomp(const sref& L,const sref& R)
49{
50 return nncase(L).compare(nncase(R));
51}
52
53#endif
diff --git a/src/ops/operator.cc b/src/ops/operator.cc
new file mode 100644
index 0000000..f668340
--- /dev/null
+++ b/src/ops/operator.cc
@@ -0,0 +1,44 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/operator.h>
21#include <algorithm>
22using namespace std;
23
24void opmap::clear() {
25 for(iterator p=begin();p!=end();p++) delete *p;
26 mrvec<opmap_t>::clear();
27}
28void opmap::erase(iterator p) {
29 delete *p; mrvec<opmap_t>::erase(p);
30}
31
32const op_t* opmap::get(const sref& t) const
33{
34 pair<const_iterator,const_iterator> p=
35 equal_range(begin(),end(),(opmap_t)0,comp_t(t));
36 return p.first!=p.second?*p.first:0;
37}
38
39const op_t* opmap::add(op_t* op)
40{
41 pair<iterator,iterator> p=equal_range(begin(),end(),(opmap_t)0,comp_t(op->name));
42 if(p.first!=p.second) { delete *p.first; return *p.first=op; }
43 else return *insert(p.second,op);
44}
diff --git a/src/ops/operator.h b/src/ops/operator.h
new file mode 100644
index 0000000..d4a7af8
--- /dev/null
+++ b/src/ops/operator.h
@@ -0,0 +1,97 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef OPERATORH
21#define OPERATORH
22
23#include <mt/mstring.h>
24#include <mt/mvec.h>
25
26const mstring lt_tag="lt";
27
28///////////////////////////////////////////////
29
30class op_env;
31struct op_t {
32 typedef void (*op1_t)(mstream&,op_env&,const sref&);
33 typedef void (*op2_t)(mstream&,op_env&,const sref&,const sref&);
34
35 mstring name,desc;
36 int pre1,pre2;
37 int left,right;
38 op1_t f1; op2_t f2;
39
40 op_t(const mstring& s,int p1,int p2,int l,int r,op1_t op1,op2_t op2,const mstring& d):
41 name(s),pre1(p1),pre2(p2),left(l),right(r),f1(op1),f2(op2),desc(d) {}
42 op_t(const mstring& s,int p1,int p2,op1_t op1,op2_t op2,const mstring& d):
43 name(s),pre1(p1),pre2(p2),left(2),right(2),f1(op1),f2(op2),desc(d) {}
44 op_t(const mstring& s,int p,op1_t op,const mstring& d):
45 name(s),pre1(p),pre2(0),left(0),right(2),f1(op),f2(0),desc(d) {}
46 op_t(const mstring& s,int p,op2_t op,const mstring& d):
47 name(s),pre1(0),pre2(p),left(2),right(2),f1(0),f2(op),desc(d) {}
48};
49
50#define OP1_IMPL(n) \
51static void impl_##n(mstream& out,op_env& env,const sref& a)
52#define OP2_IMPL(n) \
53static void impl_##n(mstream& out,op_env& env,const sref& L,const sref& R)
54
55////////////////////////////////////////////////////////////
56
57typedef op_t* opmap_t;
58
59struct opmap : public mrvec<opmap_t> {
60 typedef mrvec<opmap_t>::iterator iterator;
61 typedef mrvec<opmap_t>::const_iterator const_iterator;
62
63 struct comp_t {
64 sref key;
65 comp_t(const sref& skey) : key(skey) {}
66 bool operator()(const op_t* a,const op_t* b) const {
67 return (a?((const sref&)a->name):key)<(b?((const sref&)b->name):key);
68 }
69 };
70
71 opmap() : mrvec<opmap_t>() {}
72 ~opmap() { clear(); }
73
74 void clear(); // overrides parent
75 void erase(iterator p); // overrides parent
76
77 const op_t* get(const sref& t) const;
78 const op_t* add(op_t* op);
79};
80
81#define OP_ADD(p,f,d) M.add(new op_t(#f,p,impl_##f,d))
82#define OP_ADDN(p,f,n,d) M.add(new op_t(#n,p,impl_##f,d))
83#define OP_ADD2(p1,p2,f,n,d) M.add(new op_t(#n,p1,p2,impl_##f,impl_##f,d))
84
85///////////////////////////////////////////
86
87void opAddBasic(opmap& map);
88void opAddComp(opmap& map);
89void opAddString(opmap& map);
90inline void opAddHEXP(opmap& map) {
91 opAddBasic(map);
92 opAddComp(map);
93 opAddString(map);
94}
95void opAddLatex(opmap& map);
96
97#endif
diff --git a/src/ops/string.cc b/src/ops/string.cc
new file mode 100644
index 0000000..76b7e72
--- /dev/null
+++ b/src/ops/string.cc
@@ -0,0 +1,274 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/operator.h>
21#include <ops/nnstyle.h>
22#include <mt/mset.h>
23
24OP2_IMPL(intersect) { mset a(L),b(R),c; c.Intersection(a,b); out<<c; }
25OP2_IMPL(union) { mset a(L),b(R),c; c.Union(a,b); out<<c; }
26OP2_IMPL(difference) { mset a(L),b(R),c; c.Difference(a,b); out<<c; }
27OP2_IMPL(concats) {
28 if(L.nempty()&&R.nempty()) out<<L<<" "<<R;
29 else if(L.nempty()) out<<L;
30 else out<<R;
31}
32
33OP1_IMPL(lcase) {mstring s=a;s.tolower();out<<s;}
34OP1_IMPL(ucase) {mstring s=a;s.toupper();out<<s;}
35OP1_IMPL(nncase) {out<<nncase(a);}
36OP1_IMPL(skipws) {out<<a.right_first_not_of(cset_ws);}
37
38OP2_IMPL(eqnn) {out<<(nncomp(L,R)==0);}
39OP2_IMPL(nenn) {out<<(nncomp(L,R)!=0);}
40
41OP1_IMPL(first) {out<<First(a);}
42OP1_IMPL(last) {out<<Last(a);}
43OP1_IMPL(rest) {out<<Rest(a);}
44
45OP1_IMPL(count) {
46 sref first,rest=a; int n=0;
47 while(Split(first,rest)) n++;
48 out<<n;
49}
50
51OP2_IMPL(nth) {
52 sref first,rest=L; int n=atoi(R);
53 while(n-->0&&Split(first,rest));
54 out<<first;
55}
56
57OP2_IMPL(which) {
58 sref first,rest=L; int n=0;
59 while(Split(first,rest)) { n++; if(first==R) { out<<n; return; } }
60 out<<0;
61}
62
63OP2_IMPL(cnt) {out<<(L.find(R)>=0);}
64OP2_IMPL(cntn) {out<<(L.find(R,cset_lcase)>=0);}
65
66OP2_IMPL(concat) {out<<L<<R;}
67
68OP2_IMPL(leftand) {out<<L.leftand_first(R);}
69OP2_IMPL(left) {out<<L.left_first(R);}
70OP2_IMPL(right) {out<<L.right_first(R);}
71OP2_IMPL(past) {out<<L.past_first(R);}
72
73OP2_IMPL(rleftand) {out<<L.leftand_last(R);}
74OP2_IMPL(rleft) {out<<L.left_last(R);}
75OP2_IMPL(rright) {out<<L.right_last(R);}
76OP2_IMPL(rpast) {out<<L.past_last(R);}
77
78void opAddString(opmap& M)
79{
80 OP_ADD(32,lcase,
81 "Lower case\n"
82 "Syntax: lcase (string)\n"
83 "Returns: (string)\n"
84 );
85 OP_ADD(32,ucase,
86 "Upper case\n"
87 "Syntax: ucase (string)\n"
88 "Returns: (string)\n"
89 );
90 OP_ADD(32,nncase,
91 "NN-style case\n"
92 "Syntax: nncase (string)\n"
93 "Returns: (string)\n"
94 "\n"
95 "NN-style converts names to <lastname> <initials>\n"
96 );
97 OP_ADD(32,skipws,
98 "Skip whitespace\n"
99 "Syntax: skipws (string)\n"
100 "Returns: (string)\n"
101 "\n"
102 "Skips trailing whitespace\n"
103 );
104
105 OP_ADD(32,first,
106 "First element in list\n"
107 "Syntax: first (list)\n"
108 "Returns: (string)\n"
109 "\n"
110 "Elements are separated by whitespace\n"
111 );
112 OP_ADD(32,last,
113 "Last element in list\n"
114 "Syntax: last (list)\n"
115 "Returns: (string)\n"
116 "\n"
117 "Elements are separated by whitespace\n"
118 );
119 OP_ADD(32,rest,
120 "Rest of elements in list\n"
121 "Syntax: rest (list)\n"
122 "Returns: (list)\n"
123 "\n"
124 "Elements are separated by whitespace\n"
125 );
126 OP_ADD(32,count,
127 "Count elements in list\n"
128 "Syntax: count (list)\n"
129 "Returns: (int)\n"
130 "\n"
131 "Elements are separated by whitespace\n"
132 );
133
134 OP_ADD(30,nth,
135 "Nth element in list\n"
136 "Syntax: (list) nth (int)\n"
137 "Returns: (string)\n"
138 "\n"
139 "First element is denoted 1\n"
140 "Elements out of range returns empty\n"
141 "Elements are separated by whitespace\n"
142 );
143 OP_ADD(30,which,
144 "Which element in list\n"
145 "Syntax: (list) a which (string) b\n"
146 "Returns: (int)\n"
147 "\n"
148 "Which element in a is b (0 if not found)\n"
149 "First element is denoted 1\n"
150 "Elements are separated by whitespace\n"
151 );
152
153 OP_ADD(28,left,
154 "Left of substring\n"
155 "Syntax: (string) a left (string) b\n"
156 "Returns: (string)\n"
157 "\n"
158 "Everything in a to the left of first b, of a if b not found in a\n"
159 );
160 OP_ADD(28,leftand,
161 "Left of substring inclusive\n"
162 "Syntax: (string) a leftand (string) b\n"
163 "Returns: (string)\n"
164 "\n"
165 "Everything in a to the left of first b inclusive, of a if b not found in a\n"
166 );
167 OP_ADD(28,right,
168 "Right of substring inclusive\n"
169 "Syntax: (string) a right (string) b\n"
170 "Returns: (string)\n"
171 "\n"
172 "Everything in a to the right of first b inclusive, of empty if b not found in a\n"
173 );
174 OP_ADD(28,past,
175 "Right of substring\n"
176 "Syntax: (string) a past (string) b\n"
177 "Returns: (string)\n"
178 "\n"
179 "Everything in a to the right of first b, of empty if b not found in a\n"
180 );
181
182 OP_ADD(28,rleft,
183 "Left of substring (reversed)\n"
184 "Syntax: (string) a rleft (string) b\n"
185 "Returns: (string)\n"
186 "\n"
187 "Everything in a to the left of last b, of a if b not found in a\n"
188 );
189 OP_ADD(28,rleftand,
190 "Left of substring inclusive, (reversed)\n"
191 "Syntax: (string) a rleftand (string) b\n"
192 "Returns: (string)\n"
193 "\n"
194 "Everything in a to the left of last b inclusive, of a if b not found in a\n"
195 );
196 OP_ADD(28,rright,
197 "Right of substring inclusive (reversed)\n"
198 "Syntax: (string) a rright (string) b\n"
199 "Returns: (string)\n"
200 "\n"
201 "Everything in a to the right of last b inclusive, of empty if b not found in a\n"
202 );
203 OP_ADD(28,rpast,
204 "Right of substring (reversed)\n"
205 "Syntax: (string) a rpast (string) b\n"
206 "Returns: (string)\n"
207 "\n"
208 "Everything in a to the right of last b, of empty if b not found in a\n"
209 );
210
211 OP_ADDN(24,concat,++,
212 "String concatenation\n"
213 "Syntax: (string) ++ (string)\n"
214 "Returns: (string)\n"
215 );
216 OP_ADDN(24,concats,+++,
217 "List concatenation\n"
218 "Syntax: (list) +++ (list)\n"
219 "Returns: (list)\n"
220 "\n"
221 "Lists are concatenated with space\n"
222 );
223
224 OP_ADD(18,cnt,
225 "Contains substring\n"
226 "Syntax: (string) a cnt (string) b\n"
227 "Returns: (int)\n"
228 "\n"
229 "Nonzero if b found in a\n"
230 );
231 OP_ADD(18,cntn,
232 "Contains substring, case insensitive\n"
233 "Syntax: (string) a cnt (string) b\n"
234 "Returns: (int)\n"
235 "\n"
236 "Nonzero if b found in a\n"
237 );
238 OP_ADD(18,eqnn,
239 "NN-style equal\n"
240 "Syntax: (string) eqnn (string)\n"
241 "Returns: (int)\n"
242 "\n"
243 "NN-style converts names to <lastname> <initials>\n"
244 );
245 OP_ADD(18,nenn,
246 "NN-style not equal\n"
247 "Syntax: (string) eqnn (string)\n"
248 "Returns: (int)\n"
249 "\n"
250 "NN-style converts names to <lastname> <initials>\n"
251 );
252
253 OP_ADDN(10,intersect,&&&,
254 "List intersection\n"
255 "Syntax: (list) a &&& (list) b\n"
256 "Returns: (list)\n"
257 "\n"
258 "Finds the set intersection of a and b\n"
259 );
260 OP_ADDN(9,difference,---,
261 "List difference\n"
262 "Syntax: (list) a &&& (list) b\n"
263 "Returns: (list)\n"
264 "\n"
265 "Finds the set difference of a and b\n"
266 );
267 OP_ADDN(9,union,|||,
268 "List union\n"
269 "Syntax: (list) a &&& (list) b\n"
270 "Returns: (list)\n"
271 "\n"
272 "Finds the set union of a and b\n"
273 );
274}
diff --git a/src/ops/test.cc b/src/ops/test.cc
new file mode 100644
index 0000000..b6058fc
--- /dev/null
+++ b/src/ops/test.cc
@@ -0,0 +1,161 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <ops/express.h>
21#include <mt/msmap.h>
22#include <iostream>
23#include <fstream>
24using namespace std;
25
26static fp_stream mout(stdout),merr(stderr);
27
28struct tt_env : public op_env {
29 sspile var;
30 tt_env(opmap& map) : op_env(map) {}
31 int split(sref& first,sref& rest) throw(merror_t) {
32 static const charset spec("+-*%/<=>^_!~&|,?:;");
33 static const charset delim("()\"\\");
34 static const charset specws=spec|delim|cset_ws;
35 int s;
36 rest=rest.right_first_not_of(cset_ws);
37 if((s=rest.skip(cset_quotes))>0) {
38 first=rest.left(s);
39 rest=rest.right(s);
40 }
41 else if((s=rest.skip(cset_para))>0) {
42 first=Trim(rest.left(s),cset_para);
43 rest=rest.right(s);
44 }
45 else if((s=rest.skip(cset_braces))>0) {
46 first=rest.left(s);
47 rest=rest.right(s);
48 }
49 else if(spec.test(*rest)) {
50 first=rest.left_first_not_of(spec);
51 rest=rest.adv(first);
52 }
53 else {
54 first=rest.left_first_of(specws);
55 rest=rest.adv(first);
56 }
57 return first.nempty();
58 }
59 void term(mstream& out,expr_t* x) throw(merror_t) {
60 if(x->expr.empty()) {
61 x->status=0;
62 }
63 else if(x->expr.skip(cset_quotes)==x->expr.size()) {
64 out<<x->expr(1,-3);
65 x->status=0;
66 }
67 else if(x->expr.find_not_of(cset_real)<0) {
68 out<<x->expr;
69 x->status=0;
70 }
71 else {
72 for(sspile::iterator s=var.begin();s!=var.end();s++)
73 if(s->first==x->expr) { out<<s->second; x->status=OP_LOCAL; break; }
74 }
75 }
76};
77
78#define TT_IMPL(n) \
79static void impl_##n(mstream& out,tt_env& env,const sref& L,const sref& R)
80#define TT_ADDN(p,f,n,d) \
81M.add(new op_t(#n,0,p,1,2,0,(op_t::op2_t)impl_##f,d))
82
83TT_IMPL(assign) {
84 sspile& var=env.var;
85 for(sspile::iterator p=var.begin();p!=var.end();p++)
86 if(p->first==L) { p->second=R; return; }
87 var.push_back(sstring(L,R));
88}
89
90TT_IMPL(incr) {
91 sspile& var=env.var;
92 for(sspile::iterator p=var.begin();p!=var.end();p++)
93 if(p->first==L) { p->second=itoa(atoi(p->second)+atoi(R)); break; }
94}
95
96TT_IMPL(decr) {
97 sspile& var=env.var;
98 for(sspile::iterator p=var.begin();p!=var.end();p++)
99 if(p->first==L) { p->second=itoa(atoi(p->second)-atoi(R)); break; }
100}
101
102inline void opAddTT(opmap& M) {
103 TT_ADDN(4,assign,=,"C style");
104 TT_ADDN(4,assign,:=,"new var");
105 TT_ADDN(4,incr,+=,"C style");
106 TT_ADDN(4,decr,-=,"C style");
107}
108
109main(int argc,char* argv[]) try
110{
111 opmap ops;
112 opAddHEXP(ops);
113 opAddTT(ops);
114 tt_env env(ops);
115 mstring buf;
116 sref_t line;
117 expr_t expr;
118 if(argc>1) {
119 buf.load(sref(argv[1]));
120 sref first,rest=buf;
121 Splitln(first,rest);
122 if(first.left(2)!=sref("#!")) rest=buf;
123 (expr=buf).expand(env);
124 expr.eval(mout,env,OP_ALL);
125 mout<<"\n";
126 }
127 else {
128 while(1) {
129 merr<<"ops>";
130 cin.getline(line,sizeof(sref_t));
131 sref first,rest(line);
132 Split(first,rest);
133 if(first==sref("exit")) {
134 break;
135 }
136 else if(first==sref("tree")) {
137 expr.trav(mout,12);
138 }
139 else if(first==sref("eval")) {
140 expr.eval(mout,env,OP_ALL);
141 mout<<"\n";
142 }
143 else {
144 buf=line;
145 try {
146 (expr=buf).expand(env);
147 expr.eval(mout,env,OP_ALL);
148 mout<<"\n";
149 }
150 catch(const merror_t& e) {
151 merr<<e.desc<<"\n";
152 }
153 }
154 }
155 }
156 return 0;
157}
158catch(const merror_t& e) {
159 merr<<"ops("<<e.num<<") "<<e.desc<<"\n";
160 return -1;
161}
diff --git a/src/serv/auth.cc b/src/serv/auth.cc
new file mode 100644
index 0000000..abf16b3
--- /dev/null
+++ b/src/serv/auth.cc
@@ -0,0 +1,162 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21
22const mstring default_tag=".default";
23
24/////////////////////////////////////////////////////////////////
25
26TOK_IMPL(remote_name) { out<<Reqd(env)->tcp->node.name; }
27TOK_IMPL(remote_address) { out<<Reqd(env)->tcp->node.ip; }
28TOK_IMPL(remote_port) { out<<Reqd(env)->tcp->port; }
29
30/////////////////////////////////////////////////////////////////
31
32inline int match(const sref& rem,const sref& longrem,const sref& dom)
33{
34 if(rem==dom) return 1;
35 if(*dom!='.') return 0;
36 if(longrem.right_last(dom)==dom) return 1;
37 return 0;
38}
39
40inline int allow(const sref& uname,const sref& list)
41{
42 mstring remote=First(uname);
43 mstring longrem=remote; if(longrem.find('.')<0) longrem+=default_tag;
44 if(remote.empty()) return 0;
45 if(First(list).empty()) return 1;
46 sref first,rest=list;
47 while(Split(first,rest)) if(match(remote,longrem,first)) return 1;
48 return 0;
49}
50
51TOK_IMPL(remote_allow) { out<<allow(Reqd(env)->tcp->node.name,env[0]); }
52TOK_IMPL(bindroot) { Reqd(env)->htcd()->bindroot=env[0]; }
53
54/////////////////////////////////////////////////////////////////
55
56TOK_IMPL(user_allow) {
57 htcd_req* htcd=Reqd(env);
58 mstring opt=env.parg(-1);
59 int now=opt.empty()?time(0):atoi(opt);
60 out<<htcd->user.allow_list(env[0],now,htcd->RootAllowed());
61}
62
63TOK_IMPL(on_clear) {
64 htcd_req* htcd=Reqd(env);
65 if(htcd->user.allow_list(env[0],time(0),htcd->RootAllowed())) env.parg(out,1);
66 else env.parg(out,2);
67}
68
69/////////////////////////////////////////////////////////////////
70
71TOK_IMPL(allowed) {
72 int ok=0;
73 if(!env.db) THROW("htc: no open database");
74 if(env.dbat>=0&&env.dbat<env.db->size()) {
75 user_t user;
76 env.db->Get(env.dbat,user.list);
77 if(user.list.size()!=user_tabs)
78 THROW("htc: cannot test - probably not a users database");
79 mstring opt=env.parg(-1);
80 int now=opt.empty()?time(0):atoi(opt);
81 ok=user.allow_list(env[0],now,Reqd(env)->RootAllowed());
82 }
83 out<<ok;
84}
85
86TOK_IMPL(ingroups) {
87 int ok=0;
88 if(!env.db) THROW("htc: no open database");
89 if(env.dbat>=0&&env.dbat<env.db->size()) {
90 user_t user;
91 env.db->Get(env.dbat,user.list);
92 if(user.list.size()!=user_tabs)
93 THROW("htc: cannot test - probably not a users database");
94 mstring opt=env.parg(-1);
95 int now=opt.empty()?time(0):atoi(opt);
96 ok=user.allow_list(env[0],now,-1);
97 }
98 out<<ok;
99}
100
101/////////////////////////////////////////////////////////////////
102
103void envAddAuth(tokmap& T)
104{
105 TOK_ADD(remote_name,"",tok_t::PUBLIC,
106 "%Remote hostname\n"
107 "%Syntax: \\remote.name\n"
108 );
109 TOK_ADD(remote_address,"",tok_t::PUBLIC,
110 "%Remote address\n"
111 "%Syntax: \\remote.address\n"
112 );
113 TOK_ADD(remote_port,"",tok_t::PUBLIC,
114 "%Remote port\n"
115 "%Syntax: \\remote.port\n"
116 );
117
118 /////////////////////////////////////////////////////////////
119
120 TOK_ADD(remote_allow,"x",tok_t::PUBLIC,
121 "%True if remote hostname allowed by domain\n"
122 "%Syntax: \\remote.allow{domain list}\n"
123 "%\n"
124 "%May be used to restrict access without any group\n"
125 );
126 TOK_ADD(bindroot,"x",tok_t::SYSONLY,
127 "%Bind root access to explicit addresses\n"
128 "%Syntax: \\bindroot{address list}\n"
129 "%\n"
130 "%Note that domain syntax does not work here; you\n"
131 "%want to have total control over all root access.\n"
132 );
133
134 /////////////////////////////////////////////////////////////
135
136 TOK_ADD(user_allow,"x?",tok_t::SYSONLY,
137 "%Core test on user clearance\n"
138 "%Syntax: \\user.allow{groups}<time>\n"
139 "%\n"
140 "%In case of several groups, all must be allowed.\n"
141 );
142 TOK_ADD(on_clear,"xr?",tok_t::SYSONLY,
143 "%Do if user is allowed in all groups now\n"
144 "%Syntax: \\on.clear{groups}{body}<else>\n"
145 );
146
147 /////////////////////////////////////////////////////////////
148
149 TOK_ADD(allowed,"x?",tok_t::SYSONLY,
150 "%True if the current record is allowed in all groups now\n"
151 "%Syntax: \\allowed{groups}<time>\n"
152 "%\n"
153 "%Only used as a query function\n"
154 );
155
156 TOK_ADD(ingroups,"x?",tok_t::SYSONLY,
157 "%True if the current record is part of all groups now\n"
158 "%Syntax: \\ingroups{groups}<time>\n"
159 "%\n"
160 "%Only used as a query function\n"
161 );
162}
diff --git a/src/serv/const.cc b/src/serv/const.cc
new file mode 100644
index 0000000..f252a17
--- /dev/null
+++ b/src/serv/const.cc
@@ -0,0 +1,69 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21
22inline tok_t* Const(tokmap& map,const char* s,const sref& b) throw(merror_t) {
23 return Const(map,sref(s),b,tok_t::PUBLIC);
24}
25
26void envAddConst(tokmap& T)
27{
28 Const(T,"HTTP.100",HTTP_100);
29 Const(T,"HTTP.101",HTTP_101);
30 Const(T,"HTTP.200",HTTP_200);
31 Const(T,"HTTP.201",HTTP_201);
32 Const(T,"HTTP.202",HTTP_202);
33 Const(T,"HTTP.203",HTTP_203);
34 Const(T,"HTTP.204",HTTP_204);
35 Const(T,"HTTP.205",HTTP_205);
36 Const(T,"HTTP.206",HTTP_206);
37 Const(T,"HTTP.300",HTTP_300);
38 Const(T,"HTTP.301",HTTP_301);
39 Const(T,"HTTP.302",HTTP_302);
40 Const(T,"HTTP.303",HTTP_303);
41 Const(T,"HTTP.304",HTTP_304);
42 Const(T,"HTTP.305",HTTP_305);
43 Const(T,"HTTP.306",HTTP_306);
44 Const(T,"HTTP.307",HTTP_307);
45 Const(T,"HTTP.400",HTTP_400);
46 Const(T,"HTTP.401",HTTP_401);
47 Const(T,"HTTP.402",HTTP_402);
48 Const(T,"HTTP.403",HTTP_403);
49 Const(T,"HTTP.404",HTTP_404);
50 Const(T,"HTTP.405",HTTP_405);
51 Const(T,"HTTP.406",HTTP_406);
52 Const(T,"HTTP.407",HTTP_407);
53 Const(T,"HTTP.408",HTTP_408);
54 Const(T,"HTTP.409",HTTP_409);
55 Const(T,"HTTP.410",HTTP_410);
56 Const(T,"HTTP.411",HTTP_411);
57 Const(T,"HTTP.412",HTTP_412);
58 Const(T,"HTTP.413",HTTP_413);
59 Const(T,"HTTP.414",HTTP_414);
60 Const(T,"HTTP.415",HTTP_415);
61 Const(T,"HTTP.416",HTTP_416);
62 Const(T,"HTTP.417",HTTP_417);
63 Const(T,"HTTP.500",HTTP_500);
64 Const(T,"HTTP.501",HTTP_501);
65 Const(T,"HTTP.502",HTTP_502);
66 Const(T,"HTTP.503",HTTP_503);
67 Const(T,"HTTP.504",HTTP_504);
68 Const(T,"HTTP.505",HTTP_505);
69}
diff --git a/src/serv/direct.cc b/src/serv/direct.cc
new file mode 100644
index 0000000..1e7c2d6
--- /dev/null
+++ b/src/serv/direct.cc
@@ -0,0 +1,73 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21#include <mt/dates.h>
22
23const mstring log_cmd="\\group:\\user.id";
24
25TOK_IMPL(error) {
26 throw("htc: 'error' no longer supported");
27}
28
29TOK_IMPL(log) {
30 htcd_req* htc=Reqd(env);
31 MLOCK(htc->htcd()->mutex);
32 fp_stream& tlog=htc->htcd()->errlog;
33 tlog<<"["<<time(0)<<"]["<<htc->tcp->node.ip<<"]["
34 <<htc->tcp->node.name<<":"<<htc->tcp->port<<"]["
35 <<htc->group<<":"<<htc->user.uid()<<"] ";
36 env.parg(tlog,0);
37 tlog<<"\n";
38 tlog.flush();
39}
40
41TOK_IMPL(output) {
42 env.parg(*Reqd(env)->output,0);
43}
44
45void envAddDirect(tokmap& T)
46{
47 TOK_ADD(output,"r",tok_t::PUBLIC,
48 "%Redirect to output stream\n"
49 "%Syntax: \\output{body}\n"
50 "%\n"
51 "%Normally used on server-level, when output refers\n"
52 "%to a socket.\n"
53 );
54
55 TOK_ADD(error,"r",tok_t::SYSONLY,
56 "%Redirect to error stream\n"
57 "%Syntax: \\error{body}\n"
58 "%\n"
59 "%Normally used for debugging and loggin of errors.\n"
60 );
61
62 TOK_ADD(log,"r",tok_t::SYSONLY,
63 "%Message log\n"
64 "%Syntax: \\log{msg}\n"
65 "%\n"
66 "%Outputs to log stream a single line with pre-set information:\n"
67 "%\n"
68 "%IP address\n"
69 "%Time\n"
70 "%Request\n"
71 "%Response\n"
72 );
73}
diff --git a/src/serv/form.cc b/src/serv/form.cc
new file mode 100644
index 0000000..815f9c4
--- /dev/null
+++ b/src/serv/form.cc
@@ -0,0 +1,102 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21
22const mstring tag="T.";
23const mstring ncookie_tag="ncookie";
24const mstring multipart_tag="multipart";
25const mstring body_tag="T.body";
26
27static mstring Tag(const sref& in)
28{
29 mstring name=in;
30 for(int i=0;i<name.size();i++) if(name[i]=='_') name[i]='.';
31 if(tag.empty()||tag==name.left(tag.size())) return name;
32 name.insert(0,tag);
33 return name;
34}
35
36static void AddConst(tokmap& map,const sref& s,const sref& b) throw(merror_t)
37{
38 tok_t* p=map.get_this(s);
39 if(p) {
40 mstring nb=p->body; nb.append(1,' '); nb+=b;
41 Const(map,s,nb,tok_t::PUBLIC,1);
42 }
43 else Const(map,s,b,tok_t::PUBLIC);
44}
45
46static void PushMultipart(tokmap& map,const Mime& root) throw(merror_t)
47{
48 rpile part;
49 if(root.Multipart(part)) {
50 for(int i=0;i<part.size();i++) {
51 Mime msg(part[i]);
52 if(msg.cont_disp_name.nempty()) {
53 mstring name=Tag(msg.cont_disp_name);
54 if(msg.cont_disp_file.nempty()) {
55 reference_t* tok=Reference(map,name,msg.cont_disp_file,tok_t::PUBLIC);
56 swrite via;
57 if(eqn(msg.cont_trans_enc,trans_base64))
58 decode64(via(tok->data),msg.body);
59 else if(eqn(msg.cont_trans_enc,trans_quote))
60 decodeQP(via(tok->data),msg.body);
61 else
62 via(tok->data)<<msg.body;
63 }
64 else AddConst(map,name,msg.body);
65 }
66 }
67 }
68}
69
70static void PushWWWForm(tokmap& map,const sref& in) throw(merror_t)
71{
72 sspile tmp;
73 Unpack(tmp,in);
74 for(int i=0;i<tmp.size();i++)
75 AddConst(map,Tag(tmp[i].first),tmp[i].second);
76}
77
78void SetCookies(tokmap& map,const httpReq& req)
79{
80 Const(map,ncookie_tag,itoa(req.cookies.size()),tok_t::PUBLIC);
81 int n=0;
82 for(sspile::const_iterator p=req.cookies.begin();p!=req.cookies.end();p++) {
83 mstring name,val;
84 name.convert("cookie%d.name",n);
85 val.convert("cookie%d.val",n);
86 Const(map,name,p->first,tok_t::PUBLIC);
87 Const(map,val,p->second,tok_t::PUBLIC);
88 n++;
89 }
90 if(req.arg.nempty()) PushWWWForm(map,req.arg);
91}
92
93void envAddForm(tokmap& map,const httpReq& req)
94{
95 if(req.method==HTTP_POST) {
96 if(req.cont_type.find(multipart_tag,cset_lcase)>=0) PushMultipart(map,req);
97 else PushWWWForm(map,req.body);
98 }
99 else if(req.method==HTTP_PUT) {
100 Const(map,body_tag,req.body,tok_t::PUBLIC);
101 }
102}
diff --git a/src/serv/htcd.h b/src/serv/htcd.h
new file mode 100644
index 0000000..7eaa8dc
--- /dev/null
+++ b/src/serv/htcd.h
@@ -0,0 +1,74 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef HTCdH
21#define HTCdH
22
23#include <serv/tempmap.h>
24#include <sh/htc.h>
25#include <http/http.h>
26
27///////////////////////////////////////////////////
28
29struct HTCd : public HTC {
30 fp_stream logger,errlog;
31 mstring bindroot;
32 mutex_t mutex;
33
34 HTCd(const mstring& path);
35 ~HTCd();
36};
37
38///////////////////////////////////////////////////
39
40struct htcd_user : public htc_user {
41 htcd_user(tokmap& p,const mstring& path);
42};
43
44///////////////////////////////////////////////////
45
46struct tcpReq {
47 IPnode node;
48 int port;
49};
50
51///////////////////////////////////////////////////
52
53struct htcd_req : public htc_req {
54 mstream* output;
55 tcpReq* tcp;
56 httpReq* req;
57 httpResp resp;
58
59 HTCd* htcd() { return (HTCd*)glob; }
60
61 void AddBody(const sref& body);
62 int RootAllowed();
63
64 htcd_req(HTCd& g,tokmap& p,mstream& out,tcpReq& trec,httpReq& hrec);
65};
66
67inline htcd_req* Reqd(Env& env) throw(merror_t) { return (htcd_req*)env.req; }
68
69///////////////////////////////////////////////////
70
71void Setup(tokmap& user,HTCd& htcd);
72
73#endif
74
diff --git a/src/serv/htcs.cc b/src/serv/htcs.cc
new file mode 100644
index 0000000..42ac8e3
--- /dev/null
+++ b/src/serv/htcs.cc
@@ -0,0 +1,92 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21#include <hdb/buffer.h>
22#include <mt/lock.h>
23
24static fp_stream mout(stdout),merr(stderr);
25const mstring left="{",right="}";
26
27static int unbalanced(const sref& in)
28{
29 static const charset tag("{[(");
30 if(in.empty()) return 1;
31 sref s=in.right_first_of(tag);
32 while(s.nempty()) {
33 int p=-1;
34 switch(*s) {
35 case '{': p=s.skip(cset_braces); break;
36 case '[': p=s.skip(cset_indices); break;
37 case '(': p=s.skip(cset_para); break;
38 }
39 if(p<0) return 1;
40 s=s.adv(p).right_first_of(tag);
41 }
42 return 0;
43}
44
45main(int argc,char* argv[]) try
46{
47 NODELOCK(USERMAP);
48 if(argc<2) THROW("Usage: "<<argv[0]<<" <docroot>");
49 mstring path=argv[1];
50 if(path.back()=='/') path=path.popb();
51 HTCd htcd(path);
52 tokmap user(htcd.toks);
53 Setup(user,htcd);
54 htcd_user thr(user,path);
55 tcpReq tcp; tcp.port=0;
56 httpReq hreq; hreq.method="GET";
57 htcd_req req(htcd,thr.toks,mout,tcp,hreq);
58 Env env(htcd.ops,req,XSYSTEM);
59 if(argc>2) {
60 for(int i=3;i<argc;i++) env.xpush(left+sref(argv[i])+right);
61 mstring buffer; LoadBuffer(buffer,argv[2]);
62 if(*buffer=='#') buffer.erase(0,buffer.find('\n')+1);
63 mstream m;
64 env.eval(m,buffer,1);
65 }
66 else {
67 mstring buffer,line;
68 while(!feof(stdin)) {
69 merr<<"htcd>";
70 buffer.clear();
71 while(!feof(stdin)&&unbalanced(buffer)) {
72 getline(line,stdin);
73 buffer.append(sref(line));
74 buffer+='\n';
75 }
76 try {
77 env.parse(mout,buffer);
78 mout<<"\n";
79 }
80 catch(const merror_t& e) {
81 merr<<e.desc<<"\n";
82 }
83 }
84 }
85 return 0;
86}
87catch(const merror_t& e) {
88 merr<<"ERROR: ["<<e.desc<<"]\n";
89 return -1;
90}
91
92
diff --git a/src/serv/main.cc b/src/serv/main.cc
new file mode 100644
index 0000000..f02f10c
--- /dev/null
+++ b/src/serv/main.cc
@@ -0,0 +1,122 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21#include <hdb/buffer.h>
22
23const mstring RCURI="/sys/htcd.rc";
24const mstring TREEURI="/sys/sitemap.hdb";
25const mstring TEMPURI="/sys/temp.hdb";
26
27const mstring LOGURI="/sys/htcd.log";
28const mstring ERRURI="/sys/htcd.err";
29
30///////////////////////////////////////////////////
31
32static void OpenTREE(dbmap& db,const sref& path)
33{
34 mstring TREEMAP=path+TREEURI;
35 db.Open(TREEMAP,1);
36 if(db.Tables()==0) for(int i=0;i<tree_tabs;i++) db.InsertTable(i,tree_tab[i]);
37}
38
39static void OpenTEMP(dbmap& db,const sref& path)
40{
41 mstring TEMPMAP=path+TEMPURI;
42 db.Open(TEMPMAP,1);
43 if(db.Tables()==0) for(int i=0;i<temp_tabs;i++) db.InsertTable(i,temp_tab[i]);
44}
45
46htcd_user::htcd_user(tokmap& p,const mstring& path) : htc_user(p)
47{
48 OpenTREE(DBRef(toks,TREE_tag,ms_empty,tok_t::SYSONLY)->db,path);
49 OpenTEMP(DBRef(toks,TEMP_tag,ms_empty,tok_t::SYSONLY)->db,path);
50}
51
52///////////////////////////////////////////////////
53
54void SetCookies(tokmap& map,const httpReq& req);
55void envAddForm(tokmap& map,const httpReq& req);
56
57int htcd_req::RootAllowed()
58{
59 if(htcd()->bindroot.empty()) return 1;
60 sref first,rest=htcd()->bindroot;
61 while(Split(first,rest)) if(first==tcp->node.name) return 1;
62 return 0;
63}
64
65htcd_req::htcd_req(HTCd& g,tokmap& p,mstream& out,
66 tcpReq& trec,httpReq& hrec) : htc_req(g,p)
67{
68 output=&out;
69 tcp=&trec;
70 req=&hrec;
71 SetCookies(toks,hrec);
72}
73
74void htcd_req::AddBody(const sref& body)
75{
76 req->body=body;
77 envAddForm(toks,*req);
78}
79
80///////////////////////////////////////////////////
81
82void envAddDirect(tokmap& map);
83void envAddReq(tokmap& map);
84void envAddConst(tokmap& map);
85void envAddAuth(tokmap& map);
86void envAddTemp(tokmap& map);
87
88HTCd::HTCd(const mstring& path):
89 logger(fopen((path+LOGURI).c_str(),"a+")),
90 errlog(fopen((path+ERRURI).c_str(),"a+")),
91 HTC(path)
92{
93 envAddDirect(toks);
94 envAddReq(toks);
95 envAddConst(toks);
96 envAddAuth(toks);
97 envAddTemp(toks);
98
99 memset(&mutex,0,sizeof(mutex));
100 errlog<<"["<<time(0)<<"][MAIN][HTCd started]\n";
101 errlog.flush();
102}
103
104HTCd::~HTCd()
105{
106 fclose(errlog.fp);
107 fclose(logger.fp);
108}
109
110void Setup(tokmap& user,HTCd& htcd)
111{
112 tcpReq tcp; tcp.port=0;
113 httpReq hreq; hreq.method="GET";
114 mstream m1;
115 htcd_req req(htcd,htcd.toks,m1,tcp,hreq);
116 Env env(htcd.ops,req,XSYSTEM);
117 mstring buffer;
118 LoadBuffer(buffer,htcd.docroot+RCURI);
119 Env e(env,user,htcd.docroot+RCURI);
120 mstream m2;
121 e.parse(m2,buffer);
122}
diff --git a/src/serv/request.cc b/src/serv/request.cc
new file mode 100644
index 0000000..163797f
--- /dev/null
+++ b/src/serv/request.cc
@@ -0,0 +1,279 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21
22TOK_IMPL(req_mime_version) { out<<Reqd(env)->req->mime_version; }
23TOK_IMPL(req_cont_type) { out<<Reqd(env)->req->cont_type; }
24TOK_IMPL(req_cont_type_charset) { out<<Reqd(env)->req->cont_type_charset; }
25TOK_IMPL(req_cont_type_name) { out<<Reqd(env)->req->cont_type_name; }
26TOK_IMPL(req_cont_type_boundary) { out<<Reqd(env)->req->cont_type_boundary; }
27TOK_IMPL(req_cont_id) { out<<Reqd(env)->req->cont_id; }
28TOK_IMPL(req_cont_desc) { out<<Reqd(env)->req->cont_desc; }
29TOK_IMPL(req_cont_disp) { out<<Reqd(env)->req->cont_disp; }
30TOK_IMPL(req_cont_disp_name) { out<<Reqd(env)->req->cont_disp_name; }
31TOK_IMPL(req_cont_disp_file) { out<<Reqd(env)->req->cont_disp_file; }
32TOK_IMPL(req_cont_trans_enc) { out<<Reqd(env)->req->cont_trans_enc; }
33TOK_IMPL(req_cont_length) { out<<Reqd(env)->req->cont_length; }
34
35TOK_IMPL(req_cache) { out<<Reqd(env)->req->cache; }
36TOK_IMPL(req_connect) { out<<Reqd(env)->req->connect; }
37TOK_IMPL(req_date) { out<<Reqd(env)->req->date; }
38TOK_IMPL(req_pragma) { out<<Reqd(env)->req->pragma; }
39TOK_IMPL(req_trailer) { out<<Reqd(env)->req->trailer; }
40TOK_IMPL(req_trans_enc) { out<<Reqd(env)->req->trans_enc; }
41TOK_IMPL(req_upgrade) { out<<Reqd(env)->req->upgrade; }
42TOK_IMPL(req_via) { out<<Reqd(env)->req->via; }
43TOK_IMPL(req_warning) { out<<Reqd(env)->req->warning; }
44TOK_IMPL(req_allow) { out<<Reqd(env)->req->allow; }
45TOK_IMPL(req_cont_enc) { out<<Reqd(env)->req->cont_enc; }
46TOK_IMPL(req_cont_lang) { out<<Reqd(env)->req->cont_lang; }
47TOK_IMPL(req_cont_location) { out<<Reqd(env)->req->cont_location; }
48TOK_IMPL(req_cont_md5) { out<<Reqd(env)->req->cont_md5; }
49TOK_IMPL(req_cont_range) { out<<Reqd(env)->req->cont_range; }
50TOK_IMPL(req_expires) { out<<Reqd(env)->req->expires; }
51TOK_IMPL(req_lastmod) { out<<Reqd(env)->req->lastmod; }
52
53TOK_IMPL(req_method) { out<<Reqd(env)->req->method; }
54TOK_IMPL(req_uri) { out<<Reqd(env)->req->uri; }
55TOK_IMPL(req_arg) { out<<Reqd(env)->req->arg; }
56TOK_IMPL(req_version) { out<<Reqd(env)->req->version; }
57TOK_IMPL(req_accept) { out<<Reqd(env)->req->accept; }
58TOK_IMPL(req_accept_charset) { out<<Reqd(env)->req->accept_charset; }
59TOK_IMPL(req_accept_enc) { out<<Reqd(env)->req->accept_enc; }
60TOK_IMPL(req_accept_lang) { out<<Reqd(env)->req->accept_lang; }
61TOK_IMPL(req_accept_range) { out<<Reqd(env)->req->accept_range; }
62TOK_IMPL(req_auth) { out<<Reqd(env)->req->auth; }
63TOK_IMPL(req_expect) { out<<Reqd(env)->req->expect; }
64TOK_IMPL(req_from) { out<<Reqd(env)->req->from; }
65TOK_IMPL(req_host) { out<<Reqd(env)->req->host; }
66TOK_IMPL(req_if_match) { out<<Reqd(env)->req->if_match; }
67TOK_IMPL(req_if_mod) { out<<Reqd(env)->req->if_mod; }
68TOK_IMPL(req_if_none) { out<<Reqd(env)->req->if_none; }
69TOK_IMPL(req_if_range) { out<<Reqd(env)->req->if_range; }
70TOK_IMPL(req_if_unmod) { out<<Reqd(env)->req->if_unmod; }
71TOK_IMPL(req_max_forwards) { out<<Reqd(env)->req->max_forwards; }
72TOK_IMPL(req_proxy) { out<<Reqd(env)->req->proxy; }
73TOK_IMPL(req_range) { out<<Reqd(env)->req->range; }
74TOK_IMPL(req_referer) { out<<Reqd(env)->req->referer; }
75TOK_IMPL(req_te) { out<<Reqd(env)->req->te; }
76TOK_IMPL(req_useragent) { out<<Reqd(env)->req->user_agent; }
77
78///////////////////////////////////////////////////////////////////
79
80TOK_IMPL(resp_cookie) {
81 Reqd(env)->resp.set_cookies.push_back(cookie_t(env[0],env[1],env.parg(2)));
82}
83TOK_IMPL(resp_mime_version) { Reqd(env)->resp.mime_version=env[0]; }
84TOK_IMPL(resp_cont_type) { Reqd(env)->resp.cont_type=env[0]; }
85TOK_IMPL(resp_cont_type_charset) { Reqd(env)->resp.cont_type_charset=env[0]; }
86TOK_IMPL(resp_cont_type_name) { Reqd(env)->resp.cont_type_name=env[0]; }
87TOK_IMPL(resp_cont_type_boundary) { Reqd(env)->resp.cont_type_boundary=env[0]; }
88TOK_IMPL(resp_cont_id) { Reqd(env)->resp.cont_id=env[0]; }
89TOK_IMPL(resp_cont_desc) { Reqd(env)->resp.cont_desc=env[0]; }
90TOK_IMPL(resp_cont_disp) { Reqd(env)->resp.cont_disp=env[0]; }
91TOK_IMPL(resp_cont_disp_name) { Reqd(env)->resp.cont_disp_name=env[0]; }
92TOK_IMPL(resp_cont_disp_file) { Reqd(env)->resp.cont_disp_file=env[0]; }
93TOK_IMPL(resp_cont_trans_enc) { Reqd(env)->resp.cont_trans_enc=env[0]; }
94TOK_IMPL(resp_cont_length) { Reqd(env)->resp.cont_length=env[0]; }
95
96TOK_IMPL(resp_cache) { Reqd(env)->resp.cache=env[0]; }
97TOK_IMPL(resp_connect) { Reqd(env)->resp.connect=env[0]; }
98TOK_IMPL(resp_date) { Reqd(env)->resp.date=env[0]; }
99TOK_IMPL(resp_pragma) { Reqd(env)->resp.pragma=env[0]; }
100TOK_IMPL(resp_trailer) { Reqd(env)->resp.trailer=env[0]; }
101TOK_IMPL(resp_trans_enc) { Reqd(env)->resp.trans_enc=env[0]; }
102TOK_IMPL(resp_upgrade) { Reqd(env)->resp.upgrade=env[0]; }
103TOK_IMPL(resp_via) { Reqd(env)->resp.via=env[0]; }
104TOK_IMPL(resp_warning) { Reqd(env)->resp.warning=env[0]; }
105TOK_IMPL(resp_allow) { Reqd(env)->resp.allow=env[0]; }
106TOK_IMPL(resp_cont_enc) { Reqd(env)->resp.cont_enc=env[0]; }
107TOK_IMPL(resp_cont_lang) { Reqd(env)->resp.cont_lang=env[0]; }
108TOK_IMPL(resp_cont_location) { Reqd(env)->resp.cont_location=env[0]; }
109TOK_IMPL(resp_cont_md5) { Reqd(env)->resp.cont_md5=env[0]; }
110TOK_IMPL(resp_cont_range) { Reqd(env)->resp.cont_range=env[0]; }
111TOK_IMPL(resp_expires) { Reqd(env)->resp.expires=env[0]; }
112TOK_IMPL(resp_lastmod) { Reqd(env)->resp.lastmod=env[0]; }
113
114TOK_IMPL(resp_version) { Reqd(env)->resp.version=env[0]; }
115TOK_IMPL(resp_status) { Reqd(env)->resp.status=env[0]; }
116TOK_IMPL(resp_age) { Reqd(env)->resp.age=env[0]; }
117TOK_IMPL(resp_etag) { Reqd(env)->resp.etag=env[0]; }
118TOK_IMPL(resp_location) { Reqd(env)->resp.location=env[0]; }
119TOK_IMPL(resp_proxy_auth) { Reqd(env)->resp.proxy_authent=env[0]; }
120TOK_IMPL(resp_retry) { Reqd(env)->resp.retry=env[0]; }
121TOK_IMPL(resp_server) { Reqd(env)->resp.server=env[0]; }
122TOK_IMPL(resp_vary) { Reqd(env)->resp.vary=env[0]; }
123TOK_IMPL(resp_auth) { Reqd(env)->resp.authent=env[0]; }
124
125TOK_IMPL(resp_accept) { Reqd(env)->resp.accept=env[0]; }
126TOK_IMPL(resp_accept_charset) { Reqd(env)->resp.accept_charset=env[0]; }
127TOK_IMPL(resp_accept_enc) { Reqd(env)->resp.accept_enc=env[0]; }
128TOK_IMPL(resp_accept_lang) { Reqd(env)->resp.accept_lang=env[0]; }
129TOK_IMPL(resp_accept_range) { Reqd(env)->resp.accept_range=env[0]; }
130
131///////////////////////////////////////////////////////////////////
132
133TOK_IMPL(resp_getstatus) { out<<Reqd(env)->resp.status; }
134
135///////////////////////////////////////////////////////////////////
136
137TOK_IMPL(andarg) { sref s=Reqd(env)->req->arg; if(s.nempty()) out.put('?')<<s; }
138
139///////////////////////////////////////////////////////////////////
140
141const mstring reqhelp="%Request header entry\n";
142const mstring resphelp="%Response header entry; takes one argument\n";
143const mstring respgethelp="%Get response header entry\n";
144const mstring x_tag="x";
145
146void envAddReq(tokmap& T)
147{
148 TOK_ADD(req_mime_version,ms_empty,tok_t::PUBLIC,reqhelp);
149 TOK_ADD(req_cont_type,ms_empty,tok_t::PUBLIC,reqhelp);
150 TOK_ADD(req_cont_type_charset,ms_empty,tok_t::PUBLIC,reqhelp);
151 TOK_ADD(req_cont_type_name,ms_empty,tok_t::PUBLIC,reqhelp);
152 TOK_ADD(req_cont_type_boundary,ms_empty,tok_t::PUBLIC,reqhelp);
153 TOK_ADD(req_cont_id,ms_empty,tok_t::PUBLIC,reqhelp);
154 TOK_ADD(req_cont_desc,ms_empty,tok_t::PUBLIC,reqhelp);
155 TOK_ADD(req_cont_disp,ms_empty,tok_t::PUBLIC,reqhelp);
156 TOK_ADD(req_cont_disp_name,ms_empty,tok_t::PUBLIC,reqhelp);
157 TOK_ADD(req_cont_disp_file,ms_empty,tok_t::PUBLIC,reqhelp);
158 TOK_ADD(req_cont_trans_enc,ms_empty,tok_t::PUBLIC,reqhelp);
159 TOK_ADD(req_cont_length,ms_empty,tok_t::PUBLIC,reqhelp);
160
161 TOK_ADD(req_cache,ms_empty,tok_t::PUBLIC,reqhelp);
162 TOK_ADD(req_connect,ms_empty,tok_t::PUBLIC,reqhelp);
163 TOK_ADD(req_date,ms_empty,tok_t::PUBLIC,reqhelp);
164 TOK_ADD(req_pragma,ms_empty,tok_t::PUBLIC,reqhelp);
165 TOK_ADD(req_trailer,ms_empty,tok_t::PUBLIC,reqhelp);
166 TOK_ADD(req_trans_enc,ms_empty,tok_t::PUBLIC,reqhelp);
167 TOK_ADD(req_upgrade,ms_empty,tok_t::PUBLIC,reqhelp);
168 TOK_ADD(req_via,ms_empty,tok_t::PUBLIC,reqhelp);
169 TOK_ADD(req_warning,ms_empty,tok_t::PUBLIC,reqhelp);
170 TOK_ADD(req_allow,ms_empty,tok_t::PUBLIC,reqhelp);
171 TOK_ADD(req_cont_enc,ms_empty,tok_t::PUBLIC,reqhelp);
172 TOK_ADD(req_cont_lang,ms_empty,tok_t::PUBLIC,reqhelp);
173 TOK_ADD(req_cont_location,ms_empty,tok_t::PUBLIC,reqhelp);
174 TOK_ADD(req_cont_md5,ms_empty,tok_t::PUBLIC,reqhelp);
175 TOK_ADD(req_cont_range,ms_empty,tok_t::PUBLIC,reqhelp);
176 TOK_ADD(req_expires,ms_empty,tok_t::PUBLIC,reqhelp);
177 TOK_ADD(req_lastmod,ms_empty,tok_t::PUBLIC,reqhelp);
178
179 TOK_ADD(req_method,ms_empty,tok_t::PUBLIC,reqhelp);
180 TOK_ADD(req_uri,ms_empty,tok_t::PUBLIC,reqhelp);
181 TOK_ADD(req_arg,ms_empty,tok_t::PUBLIC,reqhelp);
182 TOK_ADD(req_version,ms_empty,tok_t::PUBLIC,reqhelp);
183 TOK_ADD(req_accept,ms_empty,tok_t::PUBLIC,reqhelp);
184 TOK_ADD(req_accept_charset,ms_empty,tok_t::PUBLIC,reqhelp);
185 TOK_ADD(req_accept_enc,ms_empty,tok_t::PUBLIC,reqhelp);
186 TOK_ADD(req_accept_lang,ms_empty,tok_t::PUBLIC,reqhelp);
187 TOK_ADD(req_accept_range,ms_empty,tok_t::PUBLIC,reqhelp);
188 TOK_ADD(req_auth,ms_empty,tok_t::PUBLIC,reqhelp);
189 TOK_ADD(req_expect,ms_empty,tok_t::PUBLIC,reqhelp);
190 TOK_ADD(req_from,ms_empty,tok_t::PUBLIC,reqhelp);
191 TOK_ADD(req_host,ms_empty,tok_t::PUBLIC,reqhelp);
192 TOK_ADD(req_if_match,ms_empty,tok_t::PUBLIC,reqhelp);
193 TOK_ADD(req_if_mod,ms_empty,tok_t::PUBLIC,reqhelp);
194 TOK_ADD(req_if_none,ms_empty,tok_t::PUBLIC,reqhelp);
195 TOK_ADD(req_if_range,ms_empty,tok_t::PUBLIC,reqhelp);
196 TOK_ADD(req_if_unmod,ms_empty,tok_t::PUBLIC,reqhelp);
197 TOK_ADD(req_max_forwards,ms_empty,tok_t::PUBLIC,reqhelp);
198 TOK_ADD(req_proxy,ms_empty,tok_t::PUBLIC,reqhelp);
199 TOK_ADD(req_range,ms_empty,tok_t::PUBLIC,reqhelp);
200 TOK_ADD(req_referer,ms_empty,tok_t::PUBLIC,reqhelp);
201 TOK_ADD(req_te,ms_empty,tok_t::PUBLIC,reqhelp);
202 TOK_ADD(req_useragent,ms_empty,tok_t::PUBLIC,reqhelp);
203
204 ///////////////////////////////////////////////////////////////
205
206 TOK_ADD(andarg,ms_empty,tok_t::PUBLIC,
207 "%Conditional output of argument string\n"
208 "%Syntax: \\andarg\n"
209 "%\n"
210 "%Outputs ?\\req.arg if \\req.arg is non-empty.\n"
211 );
212
213 TOK_ADD(resp_cookie,"xx?",tok_t::SYSONLY,
214 "%Set cookie\n"
215 "%Syntax: \\resp.cookie{name}{val}<options>\n"
216 "%\n"
217 "%Sets the cookie name to value val\n"
218 "%The options field should be on the form expected\n"
219 "%in the HTTP header, for instance\n"
220 "%domain=something; path=/; expires=http-data\n"
221 "%\n"
222 "%No newlines should be added, and remember that ; needs\n"
223 "%to be escaped.\n"
224 );
225
226 ///////////////////////////////////////////////////////////////
227
228 TOK_ADD(resp_mime_version,x_tag,tok_t::SYSONLY,resphelp);
229 TOK_ADD(resp_cont_type,x_tag,tok_t::SYSONLY,resphelp);
230 TOK_ADD(resp_cont_type_charset,x_tag,tok_t::SYSONLY,resphelp);
231 TOK_ADD(resp_cont_type_name,x_tag,tok_t::SYSONLY,resphelp);
232 TOK_ADD(resp_cont_type_boundary,x_tag,tok_t::SYSONLY,resphelp);
233 TOK_ADD(resp_cont_id,x_tag,tok_t::SYSONLY,resphelp);
234 TOK_ADD(resp_cont_desc,x_tag,tok_t::SYSONLY,resphelp);
235 TOK_ADD(resp_cont_disp,x_tag,tok_t::SYSONLY,resphelp);
236 TOK_ADD(resp_cont_disp_name,x_tag,tok_t::SYSONLY,resphelp);
237 TOK_ADD(resp_cont_disp_file,x_tag,tok_t::SYSONLY,resphelp);
238 TOK_ADD(resp_cont_trans_enc,x_tag,tok_t::SYSONLY,resphelp);
239 TOK_ADD(resp_cont_length,x_tag,tok_t::SYSONLY,resphelp);
240
241 TOK_ADD(resp_cache,x_tag,tok_t::SYSONLY,resphelp);
242 TOK_ADD(resp_connect,x_tag,tok_t::SYSONLY,resphelp);
243 TOK_ADD(resp_date,x_tag,tok_t::SYSONLY,resphelp);
244 TOK_ADD(resp_pragma,x_tag,tok_t::SYSONLY,resphelp);
245 TOK_ADD(resp_trailer,x_tag,tok_t::SYSONLY,resphelp);
246 TOK_ADD(resp_trans_enc,x_tag,tok_t::SYSONLY,resphelp);
247 TOK_ADD(resp_upgrade,x_tag,tok_t::SYSONLY,resphelp);
248 TOK_ADD(resp_via,x_tag,tok_t::SYSONLY,resphelp);
249 TOK_ADD(resp_warning,x_tag,tok_t::SYSONLY,resphelp);
250 TOK_ADD(resp_allow,x_tag,tok_t::SYSONLY,resphelp);
251 TOK_ADD(resp_cont_enc,x_tag,tok_t::SYSONLY,resphelp);
252 TOK_ADD(resp_cont_lang,x_tag,tok_t::SYSONLY,resphelp);
253 TOK_ADD(resp_cont_location,x_tag,tok_t::SYSONLY,resphelp);
254 TOK_ADD(resp_cont_md5,x_tag,tok_t::SYSONLY,resphelp);
255 TOK_ADD(resp_cont_range,x_tag,tok_t::SYSONLY,resphelp);
256 TOK_ADD(resp_expires,x_tag,tok_t::SYSONLY,resphelp);
257 TOK_ADD(resp_lastmod,x_tag,tok_t::SYSONLY,resphelp);
258
259 TOK_ADD(resp_version,x_tag,tok_t::SYSONLY,resphelp);
260 TOK_ADD(resp_status,x_tag,tok_t::SYSONLY,resphelp);
261 TOK_ADD(resp_age,x_tag,tok_t::SYSONLY,resphelp);
262 TOK_ADD(resp_etag,x_tag,tok_t::SYSONLY,resphelp);
263 TOK_ADD(resp_location,x_tag,tok_t::SYSONLY,resphelp);
264 TOK_ADD(resp_proxy_auth,x_tag,tok_t::SYSONLY,resphelp);
265 TOK_ADD(resp_retry,x_tag,tok_t::SYSONLY,resphelp);
266 TOK_ADD(resp_server,x_tag,tok_t::SYSONLY,resphelp);
267 TOK_ADD(resp_vary,x_tag,tok_t::SYSONLY,resphelp);
268 TOK_ADD(resp_auth,x_tag,tok_t::SYSONLY,resphelp);
269
270 TOK_ADD(resp_accept,x_tag,tok_t::SYSONLY,resphelp);
271 TOK_ADD(resp_accept_charset,x_tag,tok_t::SYSONLY,resphelp);
272 TOK_ADD(resp_accept_enc,x_tag,tok_t::SYSONLY,resphelp);
273 TOK_ADD(resp_accept_lang,x_tag,tok_t::SYSONLY,resphelp);
274 TOK_ADD(resp_accept_range,x_tag,tok_t::SYSONLY,resphelp);
275
276 ///////////////////////////////////////////////////////////////
277
278 TOK_ADD(resp_getstatus,ms_empty,tok_t::PUBLIC,respgethelp);
279}
diff --git a/src/serv/tempmap.cc b/src/serv/tempmap.cc
new file mode 100644
index 0000000..43b8732
--- /dev/null
+++ b/src/serv/tempmap.cc
@@ -0,0 +1,82 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <serv/htcd.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <sys/stat.h>
24
25const mstring TEMPDIR="/tmp/";
26
27inline dbmap* GetDB(Env& env)
28{
29 dbref_t* p=(dbref_t*)env.toks->get(TEMP_tag);
30 if(!env.is_clear(p)||!p->is_dbref()) THROW("htc: could not find tempfile db");
31 p->db.remap();
32 return &p->db;
33}
34
35TOK_IMPL(tempfile)
36{
37 mstring path=Reqd(env)->htcd()->docroot+TEMPDIR;
38 mstring file=Random(8),ext=env[1];
39 int fd;
40 while((fd=open((path+file+ext).c_str(),O_CREAT|O_EXCL|O_WRONLY|O_TRUNC,0600))==-1)
41 file=Random(8);
42 close(fd);
43 tempmap_t temp;
44 temp.name()=file+ext;
45 temp.start()=itoa(time(0));
46 temp.stop()=itoa(time(0)+atoi(env[0]));
47 temp.refer()=Reqd(env)->user.uid();
48 dbmap* db=GetDB(env);
49 if(db->empty()) temp.id()=itoa(1);
50 else temp.id()=itoa(atoi(db->at(db->size()-1,temp_id))+1);
51 int row=db->Insert(temp.list,1);
52 if(row<0) THROW("htc: could not add tempfile - record not unique");
53 out<<temp.name();
54}
55
56TOK_IMPL(tempfile_update)
57{
58 mstring path=Reqd(env)->htcd()->docroot+TEMPDIR;
59 time_t now=time(0);
60 dbmap* db=GetDB(env);
61 int n=0;
62 while(n<db->size()) {
63 if(now>atoi(db->at(n,temp_stop))) {
64 remove((path+db->at(n,temp_name)).c_str());
65 db->Rem(n);
66 }
67 else n++;
68 }
69}
70
71void envAddTemp(tokmap& T)
72{
73 TOK_ADD(tempfile,"xx",tok_t::SYSONLY,
74 "%Create a temporary file"
75 "%Syntax: \\tempfile{duration}{.ext}\n"
76 );
77 TOK_ADD(tempfile_update,"",tok_t::SYSONLY,
78 "%Update tempfile database\n"
79 "%Syntax: \\tempfile_update\n"
80 );
81}
82
diff --git a/src/serv/tempmap.h b/src/serv/tempmap.h
new file mode 100644
index 0000000..0b9cf5a
--- /dev/null
+++ b/src/serv/tempmap.h
@@ -0,0 +1,57 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef TEMPMAPH
21#define TEMPMAPH
22
23#include <sh/htc.h>
24
25const mstring TEMP_tag="TEMP";
26
27const int temp_tabs=5,temp_id=0,temp_name=1,temp_start=2,temp_stop=3;
28const mstring temp_tab[temp_tabs]={
29 "ID","NAME","START","STOP","REFER"
30};
31
32struct tempmap_t {
33 spile list;
34
35 tempmap_t() : list(temp_tabs) { reset(); }
36
37 mstring& id() { return list[0]; }
38 mstring& name() { return list[1]; }
39 mstring& start() { return list[2]; }
40 mstring& stop() { return list[3]; }
41 mstring& refer() { return list[4]; }
42
43 void reset() {
44 list.resize(temp_tabs);
45 id()=itoa(0);
46 name().clear();
47 start()=itoa(0);
48 stop()=itoa(0);
49 refer()=itoa(0);
50 }
51};
52
53/////////////////////////////////////////////////////////
54
55void envAddTemp(tokmap& T);
56
57#endif
diff --git a/src/sh/convert.cc b/src/sh/convert.cc
new file mode 100644
index 0000000..8828c34
--- /dev/null
+++ b/src/sh/convert.cc
@@ -0,0 +1,376 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <hdb/buffer.h>
22#include <http/http.h>
23
24static const charset htcmask("{}\\%&*$;");
25static const charset htmlmask("<&>\"");
26
27static void Mask(mstream& out,const charset& mask,const sref& msg)
28{
29 sref q,p=msg;
30 while(p.nempty()) {
31 p=p.adv(q=p.left_first_of(mask));
32 out<<q;
33 while(mask.test(p.front())) {
34 unsigned code=(unsigned char)*p; p=p.popf();
35 out<<"&#"<<code<<";";
36 }
37 }
38}
39
40TOK_IMPL(mask_htc) {
41 Mask(out,htcmask,env[0]);
42}
43
44TOK_IMPL(mask_html) {
45 Mask(out,htmlmask,env[0]);
46}
47
48TOK_IMPL(cdata) {
49 out.put('\"'); Mask(out,htmlmask,env[0]); out.put('\"');
50}
51
52//////////////////////////////////////////////////////////
53
54TOK_IMPL(wrap) {
55 int num=atoi(env[0]);
56 sref body=env[1];
57 int col=0;
58 for(int i=0;i<body.size();i++) {
59 if(cset_newl.test(body[i])) col=0; else col++;
60 if(cset_spaces.test(body[i])&&col>num) { out.put('\n'); col=0; }
61 else out.put(body[i]);
62 }
63}
64
65TOK_IMPL(htmlize) {
66 sref first,rest=env[0];
67 while(Splitln(first,rest)) {
68 Mask(out,htmlmask,first);
69 out<<"<br>\n";
70 }
71}
72
73TOK_IMPL(lf2crlf) {
74 LF2CRLF(out,env[0]);
75}
76TOK_IMPL(crlf2lf) {
77 CRLF2LF(out,env[0]);
78}
79
80//////////////////////////////////////////////////////////
81
82TOK_IMPL(twocolumn) {
83 int num=atoi(env[0]);
84 int page=atoi(env[1]);
85 sref head=env[2],mid=env[3],foot=env[4],body=env[5];
86 int row=0,col=0,pg=1;
87 out<<head;
88 for(int i=0;i<body.size()&&pg<=page;i++) {
89 if(pg==page) out.put(body[i]);
90 if(body[i]=='\n') {
91 row++;
92 if(row>=num) {
93 row=0;
94 col++;
95 if(col>=2) { col=0; pg++; }
96 else if(pg==page) { out<<mid; }
97 }
98 }
99 }
100 out<<foot;
101}
102
103//////////////////////////////////////////////////////////
104
105TOK_IMPL(encode) {
106 Pack(out,env[0]);
107}
108
109TOK_IMPL(decode) {
110 Unpack(out,env[0]);
111}
112
113TOK_IMPL(encode_header) {
114 encodeHeader(out,mime_default,env[0]);
115}
116
117TOK_IMPL(encode_base64) {
118 mstring buffer,path=DocPath(env,env[0]);
119 LoadBuffer(buffer,path);
120 encode64(out,buffer);
121}
122
123TOK_IMPL(pack) {
124 rrpile pile;
125 spile var(env.args);
126 for(int i=0;i<env.args;i++) {
127 env.parg(var[i],i);
128 pile.push_back(rrstring(var[i],env.glob(var[i])));
129 }
130 Pack(out,pile);
131}
132
133//////////////////////////////////////////////////////////
134
135TOK_IMPL(decode_base64) {
136 mstring buffer,name=env.parg(-1),uri=env.URI(env[0]),path=DocPath(env,env[0]);
137 LoadBuffer(buffer,path);
138 if(name.nempty()) {
139 swrite sw(Reference(*env.toks,name,uri,1)->data);
140 decode64(sw,buffer);
141 }
142 else decode64(out,buffer);
143}
144
145//////////////////////////////////////////////////////////
146
147TOK_IMPL(strip) {
148 sref s=env[0],a=env[1];
149 for(int i=0;i<s.size();i++) if(a.find(s[i])<0) out.put(s[i]);
150}
151
152TOK_IMPL(replace) {
153 mstring s=env[0]; sref a=env[1],b=env[2];
154 if(a!=b) { int p; while((p=s.find(a))>=0) s.replace(p,a.size(),b); }
155 out<<s;
156}
157
158//////////////////////////////////////////////////////////
159
160TOK_IMPL(left) {
161 int pad=atoi(env[1])-env[0].size();
162 out<<env[0]; while(pad-->0) out.put(' ');
163}
164TOK_IMPL(right) {
165 int pad=atoi(env[1])-env[0].size();
166 while(pad-->0) out.put(' '); out<<env[0];
167}
168
169TOK_IMPL(sub) {out<<env[0](atoi(env[1]),atoi(env[2]));}
170
171//////////////////////////////////////////////////////////
172
173TOK_IMPL(file2mime) {
174 const sref* p=file2mime(env[0]);
175 if(p) out<<*p; else out<<http_mime_default;
176}
177
178//////////////////////////////////////////////////////////
179
180TOK_IMPL(minilang) {
181 static const mstring lang_tag("\\lang");
182 sref p=env[0];
183 while(p.nempty()) {
184 sref e=p.left_first(lang_tag);
185 out<<e;
186 p=p.adv(e);
187 if(p.nempty()) {
188 p=p.adv(lang_tag.size());
189 e=p.right_first_not_of(cset_ws);
190 int n=0,s=e.skip(cset_braces);
191 while(s>0) {
192 p=e.adv(s);
193 if(n==env.req->lang) out<<e(1,s-2);
194 e=p.right_first_not_of(cset_ws);
195 s=e.skip(cset_braces);
196 n++;
197 }
198 if(n==0) out<<lang_tag;
199 if(*p==';') p=p.adv(1);
200 }
201 }
202}
203
204//////////////////////////////////////////////////////////
205
206void envAddConvert(tokmap& T)
207{
208 TOK_ADD(mask_htc,"x",tok_t::SYSONLY,
209 "%Mask HTC language\n"
210 "%Syntax: \\mask.htc{text}\n"
211 "%\n"
212 "%Converts 'hot' characters to HTML CDATA encoding\n"
213 "%CDATA encoding: &#hex;\n"
214 );
215 TOK_ADD(mask_html,"x",tok_t::PUBLIC,
216 "%Mask HTML language\n"
217 "%Syntax: \\mask.html{text}\n"
218 "%\n"
219 "%Converts 'hot' characters to HTML CDATA encoding\n"
220 "%CDATA encoding: &#hex;\n"
221 );
222 TOK_ADD(cdata,"x",tok_t::PUBLIC,
223 "%Convert to CDATA\n"
224 "%Syntax: \\cdata{text}\n"
225 "%\n"
226 "%Converts 'hot' characters to HTML CDATA encoding\n"
227 "%and encloses in \" characters\n"
228 "%\n"
229 "%HTML parsors usually does not nest the \" character,\n"
230 "%so this function is used extensively in arguments to\n"
231 "%HTML commands.\n"
232 );
233
234 ///////////////////////////////////////////////
235
236 TOK_ADD(wrap,"xx",tok_t::PUBLIC,
237 "%Wrap long lines\n"
238 "%Syntax: \\wrap{at column}{text}\n"
239 "%\n"
240 "%Wraps words that extend the given column by inserting\n"
241 "%newline characters.\n"
242 );
243 TOK_ADD(htmlize,"x",tok_t::PUBLIC,
244 "%HTMLize plain text\n"
245 "%Syntax: \\htmlize{text}\n"
246 "%\n"
247 "%Inserts a HTML break at each newline.\n"
248 );
249 TOK_ADD(lf2crlf,"x",tok_t::PUBLIC,
250 "%LF to CRLF\n"
251 "%Syntax: \\lf2crlf{text}\n"
252 "%\n"
253 "%Inserts a carriage return (CR) at each newline.\n"
254 );
255 TOK_ADD(crlf2lf,"x",tok_t::PUBLIC,
256 "%CRLF to LF\n"
257 "%Syntax: \\crlf2lf{text}\n"
258 "%\n"
259 "%Removes all carriage return (CR) characters.\n"
260 );
261
262 ///////////////////////////////////////////////
263
264 TOK_ADD(twocolumn,"xxxxxx",tok_t::PUBLIC,
265 "%Output column text\n"
266 "%Syntax: \\twocolumn{rows}{page}{head}{mid}{foot}{body}\n"
267 );
268
269 ///////////////////////////////////////////////
270
271 TOK_ADD(encode,"x",tok_t::PUBLIC,
272 "%Encode text\n"
273 "%Syntax: \\encode{text}\n"
274 "%\n"
275 "%Encodes text in x-www-form-urlencoded format (RFC HTTP)\n"
276 );
277 TOK_ADD(decode,"x",tok_t::PUBLIC,
278 "%Decode text\n"
279 "%Syntax: \\decode{text}\n"
280 "%\n"
281 "%Decodes text given in x-www-form-urlencoded format (RFC HTTP)\n"
282 );
283
284 TOK_ADD(encode_header,"x",tok_t::PUBLIC,
285 "%Encode header\n"
286 "%Syntax: \\encode.header{text}\n"
287 "%\n"
288 "%Encodes text in Quoted-printable header format (RFC MIME)\n"
289 );
290 TOK_ADD(encode_base64,"x",tok_t::PUBLIC,
291 "%Encode base64\n"
292 "%Syntax: \\encode.base64{uri}\n"
293 "%\n"
294 "%Encodes the uri, possible containing binary data,\n"
295 "%in BASE64 format (RFC MIME)\n"
296 );
297 TOK_ADD(decode_base64,"?x",tok_t::PUBLIC,
298 "%Decode base64\n"
299 "%Syntax: \\decode.base64{var}{uri}\n"
300 "%\n"
301 "%Encodes the uri, presumed to be in BASE64 format,\n"
302 "%and outputs or saves in var. (RFC MIME)\n"
303 );
304 TOK_ADD(pack,"*",tok_t::PUBLIC,
305 "%Encode text\n"
306 "%Syntax: \\pack<var><var>..\n"
307 "%\n"
308 "%Encodes a sequence of variables in\n"
309 "%x-www-form-urlencoded format (RFC HTTP)\n"
310 );
311
312 ///////////////////////////////////////////////
313
314 TOK_ADD(strip,"xx",tok_t::PUBLIC,
315 "%Strip text from special characters\n"
316 "%Syntax: \\stip{text}{chars}\n"
317 );
318 TOK_ADD(replace,"xxx",tok_t::PUBLIC,
319 "%Replace text\n"
320 "%Syntax: \\replace{text}{string}{subst}\n"
321 "%\n"
322 "%Replaces each occurence of string in text with subst.\n"
323 );
324
325 ///////////////////////////////////////////////
326
327 TOK_ADD(left,"xx",tok_t::PUBLIC,
328 "%Left-adjust text\n"
329 "%Syntax: \\left{text}{n}\n"
330 "%\n"
331 "%Outputs n characters, padding with spaces to the right.\n"
332 "%\n"
333 "%Writes out the full text if longer than n.\n"
334 );
335 TOK_ADD(right,"xx",tok_t::PUBLIC,
336 "%Right-adjust text\n"
337 "%Syntax: \\right{text}{n}\n"
338 "%\n"
339 "%Outputs n characters, padding with spaces to the left.\n"
340 "%\n"
341 "%Writes out the full text if longer than n.\n"
342 );
343
344 ///////////////////////////////////////////////
345
346 TOK_ADD(sub,"xxx",tok_t::PUBLIC,
347 "%Substring\n"
348 "%Syntax: \\sub{string}{pos}{n}\n"
349 "%\n"
350 "%Gets a substring of n characters, beginning at pos, from string.\n"
351 "%\n"
352 "%Negative pos values wraps to end.\n"
353 "%Negative n values wraps to 1+size.\n"
354 );
355
356 ///////////////////////////////////////////////
357
358 TOK_ADD(file2mime,"x",tok_t::PUBLIC,
359 "%Get MIME type\n"
360 "%Syntax: \\file2mime{path}\n"
361 "%\n"
362 "%Looks up the MIME type mapped to the extension of path.\n"
363 "%\n"
364 "%Defaults to application/octet-stream if not found.\n"
365 );
366
367 ///////////////////////////////////////////////
368
369 TOK_ADD(minilang,"x",tok_t::PUBLIC,
370 "%Parse lang only\n"
371 "%Syntax: \\minilang{body}\n"
372 "%\n"
373 "%This function is used to enable lang in html files,\n"
374 "%which otherwise are not parsed.\n"
375 );
376}
diff --git a/src/sh/dates.cc b/src/sh/dates.cc
new file mode 100644
index 0000000..a37103b
--- /dev/null
+++ b/src/sh/dates.cc
@@ -0,0 +1,138 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <mt/dates.h>
22#include <limits.h>
23
24const int ENDTIME=INT_MAX-4*SEC_PER_DAY;
25
26TOK_IMPL(endtime) { out<<ENDTIME; }
27TOK_IMPL(now) { out<<Now(); }
28TOK_IMPL(minutes) { out<<(60*atoi(env[0])); }
29TOK_IMPL(days) { out<<Days(atoi(env[0])); }
30TOK_IMPL(today) { out<<Today(atoi(env[0])); }
31TOK_IMPL(sunday) { out<<Sunday(atoi(env[0])); }
32TOK_IMPL(week) { out<<Week(env.req->lang,atoi(env[0])); }
33TOK_IMPL(month) { out<<Month(env.req->lang,atoi(env[0])); }
34TOK_IMPL(sweek) { out<<SWeek(env.req->lang,atoi(env[0])); }
35TOK_IMPL(smonth) { out<<SMonth(env.req->lang,atoi(env[0])); }
36
37////////////////////////////////////////////////////////////
38
39TOK_IMPL(time2http) { out<<httpTime(atoi(env[0])); }
40TOK_IMPL(time2htc) { out<<htcTime(env.req->lang,atoi(env[0])); }
41TOK_IMPL(htc2time) { out<<htcTime(env.req->lang,env[0]); }
42TOK_IMPL(cvttime) { out<<cvtTime(env[0]); }
43
44////////////////////////////////////////////////////////////
45
46void envAddDates(tokmap& T)
47{
48 TOK_ADD(endtime,"",tok_t::PUBLIC,
49 "%Endtime\n"
50 "%Syntax: \\endtime\n"
51 "%\n"
52 "%Last time (safely) representable by internal format\n"
53 );
54 TOK_ADD(now,"",tok_t::PUBLIC,
55 "%Now\n"
56 "%Syntax: \\now\n"
57 "%\n"
58 "%Current system time. Note that this may be out of\n"
59 "%sync with filesystem.\n"
60 );
61 TOK_ADD(minutes,"x",tok_t::PUBLIC,
62 "%Minutes in seconds\n"
63 "%Syntax: \\minutes{m}\n"
64 );
65 TOK_ADD(days,"x",tok_t::PUBLIC,
66 "%Days in seconds\n"
67 "%Syntax: \\days{d}\n"
68 );
69 TOK_ADD(today,"x",tok_t::PUBLIC,
70 "%Beginning of day\n"
71 "%Syntax: \\today{t}\n"
72 "%\n"
73 "%Get beginning of day.\n"
74 );
75 TOK_ADD(sunday,"x",tok_t::PUBLIC,
76 "%Last sunday\n"
77 "%Syntax: \\sunday{t}\n"
78 "%\n"
79 "%Get beginning of last sunday.\n"
80 );
81 TOK_ADD(week,"x",tok_t::PUBLIC,
82 "%Weekday (long)\n"
83 "%Syntax: \\week{t}\n"
84 "%\n"
85 "%Get long weekday format.\n"
86 "%Output in current language.\n"
87 );
88 TOK_ADD(month,"x",tok_t::PUBLIC,
89 "%Month (long)\n"
90 "%Syntax: \\month{t}\n"
91 "%\n"
92 "%Get long month format.\n"
93 "%Output in current language.\n"
94 );
95 TOK_ADD(sweek,"x",tok_t::PUBLIC,
96 "%Weekday (short)\n"
97 "%Syntax: \\sweek{t}\n"
98 "%\n"
99 "%Get short weekday format.\n"
100 "%Output in current language.\n"
101 );
102 TOK_ADD(smonth,"x",tok_t::PUBLIC,
103 "%Month (short)\n"
104 "%Syntax: \\smonth{t}\n"
105 "%\n"
106 "%Get short month format.\n"
107 "%Output in current language.\n"
108 );
109
110 //////////////////////////////////////////////////////
111
112 TOK_ADD(time2http,"x",tok_t::PUBLIC,
113 "%HTTP Standard Time (GMT)\n"
114 "%Syntax: \\time2http{t}\n"
115 "%\n"
116 "%Outputs time in standard HTTP format.\n"
117 );
118 TOK_ADD(time2htc,"x",tok_t::PUBLIC,
119 "%HTC Standard Time (Local)\n"
120 "%Syntax: \\time2htc{t}\n"
121 "%\n"
122 "%Outputs time in standard HTC format, which is local time.\n"
123 "%Output in current language.\n"
124 );
125 TOK_ADD(htc2time,"x",tok_t::PUBLIC,
126 "%Convert to time from HTC (Local)\n"
127 "%Syntax: \\htc2time{timestring}\n"
128 "%\n"
129 "%Converts text to local time internal format.\n"
130 );
131 TOK_ADD(cvttime,"x",tok_t::PUBLIC,
132 "%Convert user input time (Local)\n"
133 "%Syntax: \\cvttime{timestring}\n"
134 "%\n"
135 "%Tries to make an intelligent conversion of user input\n"
136 "%under the assumption that a local time is given.\n"
137 );
138}
diff --git a/src/sh/file.cc b/src/sh/file.cc
new file mode 100644
index 0000000..3d885c5
--- /dev/null
+++ b/src/sh/file.cc
@@ -0,0 +1,367 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <hdb/buffer.h>
22#include <mt/dates.h>
23#include <dirent.h>
24#include <sys/stat.h>
25
26const mstring sdot=".",sdots="..";
27
28///////////////////////////////////////////////////////////////////
29
30inline void stat(struct stat& fs,Env& env,const sref& path) throw(merror_t) {
31 if(::stat(DocPath(env,path).c_str(),&fs)<0)
32 THROW("htc: could not stat "<<path<<" - not found");
33}
34
35///////////////////////////////////////////////////////////////////
36
37TOK_IMPL(remfile) {
38 mstring path=DocPath(env,env[0]);
39 if(remove(path.c_str())<0) THROW("htc: Could not remove "<<path);
40}
41
42TOK_IMPL(renfile) {
43 mstring oldpath=DocPath(env,env[0]),newpath=DocPath(env,env[1]);
44 if(rename(oldpath.c_str(),newpath.c_str())<0)
45 THROW("htc: Could not rename "<<oldpath<<" to "<<newpath);
46}
47
48TOK_IMPL(filesafe) {
49 static const charset fsafe=cset_alphareal|'_';
50 mstring file=env[0];
51 int pos=file.rfind('/'); if(pos>=0) file=file.past(pos,1);
52 pos=file.rfind('\\'); if(pos>=0) file=file.past(pos,1);
53 while((pos=file.find(sdots))>=0) file.erase(pos,2);
54 mstring acc;
55 for(int i=0;i<file.size();i++) if(fsafe.test(file[i])) acc.append(1,file[i]);
56 out<<acc;
57}
58
59///////////////////////////////////////////////////////////////////
60
61TOK_IMPL(seturi) {
62 Req(env)->uri=env[0];
63}
64
65TOK_IMPL(uri) {
66 out<<Req(env)->uri;
67}
68
69TOK_IMPL(pwd) {
70 out<<Req(env)->uri.left_last('/');
71}
72
73TOK_IMPL(npwd) {
74 mstring s=Req(env)->uri.left_last('/');
75 for(int i=0;i<MAXLANG;i++) {
76 if(s.past_first('/').left_first('/')==LANG[i]) {
77 s=s.past_first('/').right_first('/');
78 break;
79 }
80 }
81 out<<s;
82}
83
84TOK_IMPL(home) {
85 if(Req(env)->htc()->docroot.nempty())
86 THROW("htc: home only works in absolute file mode");
87 out<<htchome();
88}
89
90///////////////////////////////////////////////////////////////////
91
92TOK_IMPL(load) {
93 mstring name=env.parg(-1),uri=env.URI(env[0]),path=DocPath(env,uri);
94 if(name.nempty()) LoadBuffer(Reference(*env.toks,name,uri,1)->data,path);
95 else { mstring buffer; LoadBuffer(buffer,path); out<<buffer; }
96}
97
98TOK_IMPL(open) {
99 mstring name=env[0],uri=env.URI(env[1]),path=DocPath(env,uri);
100 dbref_t* ref=DBRef(*env.toks,env[0],ms_empty,tok_t::PRIVATE,1);
101 ref->db.Open(path,atoi(env.parg(-1)));
102}
103
104TOK_IMPL(save) {
105 mstring path=DocPath(env,env[0]),var=env[1];
106 int prot=atoi(env.parg(2)); if(!prot) prot=0600;
107 tok_t* p=env.toks->get(var);
108 if(!p) THROW("htc: "<<var<<": no such variable");
109 if(p->is_reference()) SaveBuffer(((reference_t*)p)->data,path,prot);
110 else if(p->is_dbref()) ((dbref_t*)p)->db.Saveas(path,prot);
111 else SaveBuffer(p->body,path,prot);
112}
113
114TOK_IMPL(dbmod) {
115 dbref_t* p=(dbref_t*)env.toks->get(env[0]);
116 if(!p&&!p->is_dbref()) THROW("htc: "<<env[0]<<": no such database");
117 out<<p->db.Lastmod();
118}
119
120///////////////////////////////////////////////////////////////////
121
122static void Run(mstream& out,Env& env,const mstring& path) throw(merror_t) {
123 mstring buffer;
124 LoadBuffer(buffer,path);
125 env.parse(out,buffer);
126}
127
128TOK_IMPL(include) {
129 mstring cwd=env.URI(env[0]),path=DocPath(env,cwd);
130 if(!env.glob_find(cwd)) {
131 env.toks->add(new tok_t(cwd,ms_empty,tok_t::CONSTANT|tok_t::PRIVATE),0,1);
132 mstream m;
133 Env e(env,env.mod,cwd);
134 Run(m,e,path);
135 }
136}
137
138TOK_IMPL(parse) {
139 mstring cwd=env.URI(env[0]),path=DocPath(env,cwd);
140 Env e(env,env.mod,cwd);
141 Run(out,e,path);
142}
143
144TOK_IMPL(parse_private) {
145 mstring cwd=env.URI(env[0]),path=DocPath(env,cwd);
146 Env e(env,XPRIVATE,cwd);
147 Run(out,e,path);
148}
149
150TOK_IMPL(parse_public) {
151 mstring cwd=env.URI(env[0]),path=DocPath(env,cwd);
152 Env e(env,XPUBLIC,cwd);
153 Run(out,e,path);
154}
155
156///////////////////////////////////////////////////////////////////
157
158TOK_IMPL(dirent) {
159 mstring uri=env.URI(env[0]);
160 sref uribase=uri.leftand_last('/'),ext=uri.adv(uribase);
161 mstring dirpath=DocPath(env,uribase);
162 DIR* dir=opendir(dirpath.c_str());
163 if(dir) {
164 dirent* p;
165 while((p=readdir(dir))!=0) {
166 sref name(p->d_name);
167 if(name.empty()||name==sdot||name==sdots) continue;
168 if(ext.empty()||name.right(-ext.size()-1)==ext) out<<uribase<<name<<"\n";
169 }
170 closedir(dir);
171 }
172}
173
174TOK_IMPL(dirmod) {
175 struct stat fs;
176 if(::stat(DocPath(env,env[0]).c_str(),&fs)>=0) out<<fs.st_mode;
177 else out<<(int)0;
178}
179
180TOK_IMPL(dirmtime) { struct stat fs; stat(fs,env,env[0]); out<<fs.st_mtime; }
181TOK_IMPL(diruid) { struct stat fs; stat(fs,env,env[0]); out<<fs.st_uid; }
182TOK_IMPL(dirgid) { struct stat fs; stat(fs,env,env[0]); out<<fs.st_gid; }
183TOK_IMPL(filesize) { struct stat fs; stat(fs,env,env[0]); out<<fs.st_size; }
184
185TOK_IMPL(setperm) {
186 mstring path=DocPath(env,env[0]);
187 if(chmod(path.c_str(),atoi(env[1]))<0)
188 THROW("htc: could not set file permission for "<<path);
189}
190
191///////////////////////////////////////////////////////////////////
192
193void envAddFile(tokmap& T)
194{
195 TOK_ADD(remfile,"x",tok_t::SYSONLY,
196 "%Remove file\n"
197 "%Syntax: \\remfile{uri}\n"
198 );
199 TOK_ADD(renfile,"xx",tok_t::SYSONLY,
200 "%Rename file\n"
201 "%Syntax: \\renfile{olduri}{newuri}\n"
202 );
203 TOK_ADD(filesafe,"x",tok_t::PUBLIC,
204 "%Transform uri to something safe to save\n"
205 "%Syntax: \\filesafe{uri}\n"
206 "%\n"
207 "%Basically removes eventual path information and\n"
208 "%odd characters.\n"
209 );
210
211 ////////////////////////////////////////////////////////
212
213 TOK_ADD(seturi,"x",tok_t::SYSONLY,
214 "%Set current uri of current request\n"
215 "%Syntax: \\seturi\n"
216 "%\n"
217 "%Always points to a (virtual) uri.\n"
218 );
219 TOK_ADD(uri,"",tok_t::PUBLIC,
220 "%uri of current request\n"
221 "%Syntax: \\uri\n"
222 "%\n"
223 "%Always points to a (virtual) uri.\n"
224 );
225 TOK_ADD(pwd,"",tok_t::PUBLIC,
226 "%uri/directory of current request\n"
227 "%Syntax: \\pwd\n"
228 "%\n"
229 "%Always points to a (virtual) directory, and never contain any\n"
230 "%trailing slashes.\n"
231 );
232 TOK_ADD(npwd,"",tok_t::PUBLIC,
233 "%uri/directory of current request, without language reference\n"
234 "%Syntax: \\npwd\n"
235 "%\n"
236 "%Always points to a (virtual) directory, and never contain any\n"
237 "%trailing slashes.\n"
238 );
239 TOK_ADD(home,"",tok_t::PRIVATE,
240 "%Home directory\n"
241 "%Syntax: \\home\n"
242 "%\n"
243 "%Only works in absolute path mode, i.e. when no docroot is set.\n"
244 );
245
246 ////////////////////////////////////////////////////////
247
248 TOK_ADD(load,"?x",tok_t::PRIVATE,
249 "%Load file directly to output or to variable\n"
250 "%Syntax: \\load<varname>{uri}\n"
251 );
252 TOK_ADD(open,"xx?",tok_t::SYSONLY,
253 "%Open database to variable\n"
254 "%Syntax: \\load{varname}{uri}<update>\n"
255 "%\n"
256 "%If update is true, the database is opened for reading\n"
257 "%and writing. NOTE that all updates are syncronous and\n"
258 "%instantly - saves or locks are not needed.\n"
259 );
260 TOK_ADD(save,"xx?",tok_t::SYSONLY,
261 "%Save variable to file\n"
262 "%Syntax: \\save{uri}{varname}<prot>\n"
263 "%\n"
264 "%If the variable points to a reference object, the\n"
265 "%reference is saved. If it points to a database,\n"
266 "%the database is saved. For globals and functions,\n"
267 "%the body is saved.\n"
268 "%\n"
269 "%The optional prot argument is a (base 10) integer\n"
270 "%defining the creation mode mask (unix).\n"
271 );
272 TOK_ADD(dbmod,"x",tok_t::PUBLIC,
273 "%Get modification time of open database\n"
274 "%Syntax: \\dbmod{var}\n"
275 );
276
277 ////////////////////////////////////////////////////////
278
279 TOK_ADD(include,"x",tok_t::PRIVATE,
280 "%Include file in current running mode\n"
281 "%Syntax: \\include{uri}\n"
282 "%\n"
283 "%The file is loaded and evaluated, but produces no output\n"
284 "%Any uri can only be included once, so it is safe to use\n"
285 "%include as a precondition.\n"
286 "%\n"
287 "%NOTE that files parsed this way must be known to\n"
288 "%the super-user in order not to create a security hole -\n"
289 "%especially since this command is open in private mode also.\n"
290 );
291
292 TOK_ADD(parse,"x",tok_t::SYSONLY,
293 "%Parse file in current running mode\n"
294 "%Syntax: \\parse{uri}\n"
295 "%\n"
296 "%The file is loaded and evaluated to output.\n"
297 "%\n"
298 "%NOTE that files parsed this way must be known to\n"
299 "%the super-user in order not to create a security hole.\n"
300 );
301
302 TOK_ADD(parse_private,"x",tok_t::PRIVATE,
303 "%Parse file in private mode\n"
304 "%Syntax: \\parse.private{uri}\n"
305 "%\n"
306 "%The file is loaded and evaluated to output.\n"
307 "%\n"
308 "%System-mode commands are silently ignored.\n"
309 );
310
311 TOK_ADD(parse_public,"x",tok_t::PRIVATE,
312 "%Parse file in public mode\n"
313 "%Syntax: \\parse.public{uri}\n"
314 "%\n"
315 "%The file is loaded and evaluated to output.\n"
316 "%\n"
317 "%System/Private mode commands are silently ignored.\n"
318 );
319
320 ////////////////////////////////////////////////////////
321
322 TOK_ADD(dirent,"x",tok_t::SYSONLY,
323 "%Collect directory entries\n"
324 "%Syntax: \\dirent{uri/match}\n"
325 "%\n"
326 "%An argument of anydir/ collects all files in anydir.\n"
327 "%An argument of anydir/.ext collects all files ending with .ext\n"
328 "%\n"
329 "%Note that an argument of anydir collects files in the parent\n"
330 "%directory of anydir which end whith anydir, which probably is\n"
331 "%not what you want. Trailing slashes are important.\n"
332 );
333 TOK_ADD(dirmod,"x",tok_t::SYSONLY,
334 "%Return file mode of uri\n"
335 "%Syntax: \\dirmod{uri}\n"
336 "%\n"
337 "%dirmod uses the unix stat function.\n"
338 "%On failure to read, returns zero.\n"
339 );
340 TOK_ADD(dirmtime,"x",tok_t::SYSONLY,
341 "%Return modification time of uri\n"
342 "%Syntax: \\dirmtime{uri}\n"
343 );
344 TOK_ADD(diruid,"x",tok_t::SYSONLY,
345 "%Return UNIX uid of uri\n"
346 "%Syntax: \\diruid{uri}\n"
347 "%\n"
348 "%Note that the UNIX uid is different from the HTC one.\n"
349 );
350 TOK_ADD(dirgid,"x",tok_t::SYSONLY,
351 "%Return UNIX gid of uri\n"
352 "%Syntax: \\dirgid{uri}\n"
353 "%\n"
354 "%Note that the UNIX gid is different from the HTC one.\n"
355 );
356 TOK_ADD(filesize,"x",tok_t::SYSONLY,
357 "%Return filesize of uri\n"
358 "%Syntax: \\filesize{uri}\n"
359 );
360 TOK_ADD(setperm,"xx",tok_t::SYSONLY,
361 "%Set file permissions of uri\n"
362 "%Syntax: \\setperm{uri}{mode}\n"
363 "%\n"
364 "%Mode is an integer bitmask compliant with fcntl.\n"
365 );
366
367}
diff --git a/src/sh/htc.cc b/src/sh/htc.cc
new file mode 100644
index 0000000..9a87f2c
--- /dev/null
+++ b/src/sh/htc.cc
@@ -0,0 +1,92 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <hdb/buffer.h>
22#include <mt/lock.h>
23
24const mstring RCPATH=htchome()+sref("/htc/htc.rc");
25const mstring left="{",right="}";
26static fp_stream mout(stdout),merr(stderr);
27
28static int unbalanced(const sref& in)
29{
30 static const charset tag("{[(");
31 if(in.empty()) return 1;
32 sref s=in.right_first_of(tag);
33 while(s.nempty()) {
34 int p=-1;
35 switch(*s) {
36 case '{': p=s.skip(cset_braces); break;
37 case '[': p=s.skip(cset_indices); break;
38 case '(': p=s.skip(cset_para); break;
39 }
40 if(p<0) return 1;
41 s=s.adv(p).right_first_of(tag);
42 }
43 return 0;
44}
45
46main(int argc,char* argv[]) try
47{
48 NODELOCK(USERMAP);
49 HTC htc(ms_empty);
50 htc_user user(htc.toks);
51 htc_req req(htc,user.toks); req.uri=Cwd();
52 Env env(htc.ops,req,XSYSTEM);
53 if(argc>1) {
54 for(int i=2;i<argc;i++) env.xpush(left+sref(argv[i])+right);
55 mstring buffer; LoadBuffer(buffer,argv[1]);
56 if(*buffer=='#') buffer.erase(0,buffer.find('\n')+1);
57 env.eval(mout,buffer,1);
58 }
59 else {
60 mstring buffer,line;
61 if(buffer.load(RCPATH.c_str())>=0) {
62 Env e(env,user.toks,RCPATH);
63 mstream m;
64 e.parse(m,buffer);
65 }
66 while(!feof(stdin)) {
67 merr<<"htc>";
68 buffer.clear();
69 while(!feof(stdin)&&unbalanced(buffer)) {
70 getline(line,stdin);
71 buffer.append(line);
72 buffer+='\n';
73 }
74 try {
75 env.parse(mout,buffer);
76 mout<<"\n";
77 }
78 catch(const merror_t& e) {
79 merr<<e.desc<<"\n";
80 }
81 }
82 }
83 return 0;
84}
85catch(const merror_t& e) {
86 merr<<"ERROR: ["<<e.desc<<"]\n";
87 return -1;
88}
89catch(...) {
90 merr<<"ERROR: [FATAL]\n";
91 return -1;
92}
diff --git a/src/sh/htc.h b/src/sh/htc.h
new file mode 100644
index 0000000..b566176
--- /dev/null
+++ b/src/sh/htc.h
@@ -0,0 +1,77 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef HTCH
21#define HTCH
22
23#include <sh/user.h>
24#include <lang/env.h>
25#include <mt/config.h>
26
27///////////////////////////////////////////////////
28
29mstring Cwd();
30
31const mstring USERMAP=htchome()+sref("/htc/users.hdb");
32
33///////////////////////////////////////////////////
34
35struct HTC : public Lang {
36 fp_stream syslog;
37 mstring docroot,username;
38 mstring host,domain,mailer;
39 IPnode node;
40 int port;
41
42 HTC(const sref& root);
43 ~HTC();
44
45 void setHost(const sref& s);
46 void setDomain(const sref& s);
47 void setPort(int p);
48 void setMailer(const sref& s);
49};
50
51///////////////////////////////////////////////////
52
53struct htc_user {
54 tokmap toks;
55
56 htc_user(tokmap& p);
57};
58
59///////////////////////////////////////////////////
60
61struct htc_req : public req_env {
62 mstring group;
63 user_t user;
64
65 HTC* htc() { return (HTC*)glob; }
66
67 htc_req(HTC& g,tokmap& p);
68};
69
70inline htc_req* Req(Env& env) { return (htc_req*)env.req; }
71inline const sref& DocRoot(Env& env) { return Req(env)->htc()->docroot; }
72inline mstring DocPath(Env& env,const sref& uri) { return DocRoot(env)+env.URI(uri); }
73
74///////////////////////////////////////////////////
75
76#endif
77
diff --git a/src/sh/main.cc b/src/sh/main.cc
new file mode 100644
index 0000000..4926b77
--- /dev/null
+++ b/src/sh/main.cc
@@ -0,0 +1,129 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <pwd.h>
22#include <sys/stat.h>
23#include <sys/utsname.h>
24
25const mstring PREFSMAP=htchome()+sref("/htc/prefs.hdb");
26const mstring SYSLOG=htchome()+sref("/log/htc.log");
27
28static fp_stream mout(stdout),merr(stderr);
29
30///////////////////////////////////////////////////
31
32mstring Cwd() {
33 static char buf[1024];
34 mstring cwd=getcwd(buf,1024);
35 cwd+='/';
36 return cwd;
37}
38
39///////////////////////////////////////////////////
40
41static void OpenUSERS(dbmap& db)
42{
43 db.Open(USERMAP,1);
44 if(db.Tables()==0) for(int i=0;i<user_tabs;i++) db.InsertTable(i,user_tab[i]);
45}
46
47static void OpenPREFS(dbmap& db)
48{
49 db.Open(PREFSMAP,1);
50 if(db.Tables()==0) for(int i=0;i<prefs_tabs;i++) db.InsertTable(i,prefs_tab[i]);
51}
52
53htc_user::htc_user(tokmap& p) : toks(p)
54{
55 OpenUSERS(DBRef(toks,USERS_tag,ms_empty,tok_t::SYSONLY)->db);
56 OpenPREFS(DBRef(toks,PREFS_tag,ms_empty,tok_t::SYSONLY)->db);
57}
58
59///////////////////////////////////////////////////
60
61htc_req::htc_req(HTC& g,tokmap& p) : req_env(g,p)
62{
63 user.reset();
64}
65
66///////////////////////////////////////////////////
67
68void envAddFile(tokmap& map);
69void envAddConvert(tokmap& map);
70void envAddDates(tokmap& map);
71void envAddUser(tokmap& map) throw(merror_t);
72void envAddTree(tokmap& map);
73void envAddSys(tokmap& map);
74void envAddNet(tokmap& map);
75
76///////////////////////////////////////////////////
77
78HTC::HTC(const sref& root):
79 syslog(fopen(SYSLOG.c_str(),"a+"))
80{
81 docroot=root; if(docroot.back()=='/') docroot=docroot.popb();
82 username=getpwuid(getuid())->pw_name;
83
84 envAddFile(toks);
85 envAddConvert(toks);
86 envAddDates(toks);
87 envAddUser(toks);
88 envAddTree(toks);
89 envAddSys(toks);
90 envAddNet(toks);
91}
92
93///////////////////////////////////////////////////
94
95HTC::~HTC()
96{
97 fclose(syslog.fp);
98}
99
100///////////////////////////////////////////////////
101
102void HTC::setHost(const sref& s)
103{
104 host=s;
105 if(!Lookup(node,host)) THROW("sys: host "<<host<<" not listed in nameserver");
106}
107
108///////////////////////////////////////////////////
109
110void HTC::setDomain(const sref& s)
111{
112 domain=s;
113}
114
115///////////////////////////////////////////////////
116
117void HTC::setPort(int p)
118{
119 port=p;
120}
121
122///////////////////////////////////////////////////
123
124void HTC::setMailer(const sref& s)
125{
126 mailer=s;
127}
128
129///////////////////////////////////////////////////
diff --git a/src/sh/net.cc b/src/sh/net.cc
new file mode 100644
index 0000000..dc03901
--- /dev/null
+++ b/src/sh/net.cc
@@ -0,0 +1,122 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21
22/////////////////////////////////////////////////////////////////
23
24TOK_IMPL(sethost)
25{
26 Req(env)->htc()->setHost(env[0]);
27}
28TOK_IMPL(setdomain)
29{
30 Req(env)->htc()->setDomain(env[0]);
31}
32TOK_IMPL(setport)
33{
34 Req(env)->htc()->setPort(atoi(env[0]));
35}
36TOK_IMPL(setmailer)
37{
38 Req(env)->htc()->setMailer(env[0]);
39}
40
41/////////////////////////////////////////////////////////////////
42
43TOK_IMPL(HOST) {
44 out<<Req(env)->htc()->host;
45}
46
47TOK_IMPL(HOSTIP) {
48 out<<Req(env)->htc()->node.ip;
49}
50
51TOK_IMPL(DOMAIN) {
52 out<<Req(env)->htc()->domain;
53}
54
55TOK_IMPL(ROOT) {
56 out<<Req(env)->htc()->username;
57 if(Req(env)->htc()->domain.size()) out<<"@"<<Req(env)->htc()->domain;
58}
59
60TOK_IMPL(ADMIN) {
61 out<<Req(env)->htc()->username;
62 if(Req(env)->htc()->domain.size()) out<<"@"<<Req(env)->htc()->domain;
63}
64
65TOK_IMPL(port)
66{
67 out<<Req(env)->htc()->port;
68}
69
70/////////////////////////////////////////////////////////////
71
72void envAddNet(tokmap& T)
73{
74 TOK_ADD(sethost,"x",tok_t::SYSONLY,
75 "%Set host name\n"
76 "%Syntax: \\sethost{host}\n"
77 );
78 TOK_ADD(setdomain,"x",tok_t::SYSONLY,
79 "%Set default domain\n"
80 "%Syntax: \\setdomain{domain}\n"
81 );
82 TOK_ADD(setport,"x",tok_t::SYSONLY,
83 "%Set host port number\n"
84 "%Syntax: \\setport{port}\n"
85 );
86 TOK_ADD(setmailer,"x",tok_t::SYSONLY,
87 "%Set mail program path\n"
88 "%Syntax: \\setmailer{path}\n"
89 );
90
91 /////////////////////////////////////////////////////////////
92
93 TOK_ADD(HOST,"",tok_t::PUBLIC,
94 "%Host name\n"
95 "%Syntax: \\HOST\n"
96 );
97
98 TOK_ADD(HOSTIP,"",tok_t::PUBLIC,
99 "%Host IP address\n"
100 "%Syntax: \\HOSTIP\n"
101 );
102
103 TOK_ADD(DOMAIN,"",tok_t::PUBLIC,
104 "%Default domain\n"
105 "%Syntax: \\DOMAIN\n"
106 );
107
108 TOK_ADD(ROOT,"",tok_t::PUBLIC,
109 "%htcroot email address\n"
110 "%Syntax: \\ROOT\n"
111 );
112
113 TOK_ADD(ADMIN,"",tok_t::PUBLIC,
114 "%admin email address\n"
115 "%Syntax: \\ADMIN\n"
116 );
117
118 TOK_ADD(port,"",tok_t::PUBLIC,
119 "%Host port number\n"
120 "%Syntax: \\port\n"
121 );
122}
diff --git a/src/sh/string.cc b/src/sh/string.cc
new file mode 100644
index 0000000..8075a5b
--- /dev/null
+++ b/src/sh/string.cc
@@ -0,0 +1,32 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <htc.h>
21#include <mset.h>
22
23static mstring empty;
24
25TOK_IMPL(tolower) {mstring s=env[0];s.tolower();out<<s;}
26TOK_IMPL(toupper) {mstring s=env[0];s.toupper();out<<s;}
27
28void envAddString(tokmap& T)
29{
30 TOK_ADD(tolower,1,0,tok_t::PUBLIC,"%(s)");
31 TOK_ADD(toupper,1,0,tok_t::PUBLIC,"%(s)");
32}
diff --git a/src/sh/sys.cc b/src/sh/sys.cc
new file mode 100644
index 0000000..b70991b
--- /dev/null
+++ b/src/sh/sys.cc
@@ -0,0 +1,152 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <mime/mime.h>
22#include <mt/lookup.h>
23#include <mt/issue.h>
24#include <mt/dates.h>
25#include <unistd.h>
26
27////////////////////////////////////////////
28
29TOK_IMPL(sleep) { sleep(atoi(env[0])); }
30TOK_IMPL(throw) { THROW(env[0]); }
31
32////////////////////////////////////////////
33
34TOK_IMPL(sync) { dbmap::Sync(); }
35
36////////////////////////////////////////////
37
38TOK_IMPL(gethost) {
39 IPnode node; if(Lookup(node,env[0])) out<<node.name; else out<<"UNKNOWN";
40}
41
42////////////////////////////////////////////
43
44TOK_IMPL(mail) {
45 mswrite ms;
46 if(env[0].size()<2) return;
47 ms<<"From: "; encodeHeader(ms,mime_default,env[3]); ms<<" <"<<env[0]<<">\n";
48
49 //if(env[1].nempty()) ms<<"Reply-To: "<<env[1]<<"\n";
50 //!! neat simple hack - never used except as should be
51 if(env[1].nempty()) ms<<"To: "<<env[1]<<"\n";
52
53 ms<<"Date: "<<httpTime(atoi(env[4]))<<"\n";
54 ms<<"Subject: "; encodeHeader(ms,mime_default,env[5]); ms<<"\n";
55 ms<<"MIME-Version: 1.0\n";
56 ms<<"Content-Transfer-Encoding: Quoted-Printable\n";
57 ms<<"Content-Type: "<<env[6]<<"\n";
58 mswrite body; encodeQP(body,env[7]);
59 ms<<"Content-Length: "<<body.str().size()<<"\n";
60 ms<<"\n";
61 ms<<body.str();
62 HTC* htc=Req(env)->htc();
63 if(htc->mailer.size()) {
64 issue_t cmd(htc->mailer+sref(" ")+env[2]);
65 mstream m;
66 cmd.run(m,ms.str());
67 htc->syslog<<"["<<time(0)<<"][mail]["<<env[2]<<"]\n";
68 }
69 else {
70 htc->syslog<<"["<<time(0)<<"][NOT SET]["<<env[2]<<"]\n";
71 htc->syslog<<"-----------------------------------------\n";
72 htc->syslog<<ms.str()<<"\n";
73 htc->syslog<<"=========================================\n";
74 }
75 htc->syslog.flush();
76}
77
78////////////////////////////////////////////
79
80TOK_IMPL(issue) {
81 HTC* htc=Req(env)->htc();
82 htc->syslog<<"["<<time(0)<<"][issue]["<<env[0]<<"]\n";
83 htc->syslog.flush();
84 issue_t cmd(DocPath(env,env[0]));
85 cmd.run(out,env[1]);
86 htc->syslog<<"["<<time(0)<<"][finish]["<<env[0]<<"]\n";
87 htc->syslog.flush();
88}
89
90//////////////////////////////////////////////////////////
91
92void envAddSys(tokmap& T)
93{
94 TOK_ADD(sleep,"x",tok_t::SYSONLY,
95 "%Sleep for seconds\n"
96 "%Syntax: \\sleep{t}\n"
97 "%\n"
98 "%This one works just like the UNIX command\n"
99 );
100 TOK_ADD(throw,"x",tok_t::SYSONLY,
101 "%Throw an exception\n"
102 "%Syntax: \\throw{text}\n"
103 "%\n"
104 "%Throw a, for the HTC system, standard error\n"
105 "%expection, which also many of the built-in\n"
106 "%do. Enables well-behaved error handling.\n"
107 );
108
109 /////////////////////////////////////////////////////////////
110
111 TOK_ADD(sync,"",tok_t::SYSONLY,
112 "%Syncronize all open writable databases\n"
113 "%Syntax: \\sync\n"
114 "%\n"
115 "%Use in crontab only.\n"
116 );
117
118 /////////////////////////////////////////////////////////////
119
120 TOK_ADD(gethost,"x",tok_t::SYSONLY,
121 "%Lookup hostname on nameserver\n"
122 "%Syntax: \\gethost{IP address}\n"
123 "%\n"
124 "%Normally performed automatically by the server.\n"
125 );
126
127 /////////////////////////////////////////////////////////////
128
129 TOK_ADD(mail,"xxxxxxxx",tok_t::SYSONLY,
130 "%System mail\n"
131 "%Syntax: \\mail{from}{replyto}{to}{fromname}{date}{subject}{mime}{body}\n"
132 "%\n"
133 "%This mail command can do almost anything, so be careful!\n"
134 "%Usually there are several htc commands simplifying the use\n"
135 "%of this one.\n"
136 );
137
138 /////////////////////////////////////////////////////////////
139
140 TOK_ADD(issue,"xx",tok_t::SYSONLY,
141 "%Issue piped command\n"
142 "%Syntax: \\issue{uri}{stdin}\n"
143 "%\n"
144 "%Pipes stdin to cmd and output stdout.\n"
145 "%An extremely powerful command that may be used\n"
146 "%to run external programs via the web.\n"
147 "%\n"
148 "%Note that the normal uri handling is performed.\n"
149 );
150
151 /////////////////////////////////////////////////////////////
152}
diff --git a/src/sh/tree.cc b/src/sh/tree.cc
new file mode 100644
index 0000000..0ec8f16
--- /dev/null
+++ b/src/sh/tree.cc
@@ -0,0 +1,304 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21#include <sh/user.h>
22#include <hdb/buffer.h>
23#include <http/http.h>
24#include <mt/dates.h>
25#include <sys/stat.h>
26
27const mstring index_tag="index.htc";
28const mstring sindex_tag="/index.htc";
29const mstring htc_mime="text/x-htc";
30const mstring htx_mime="text/x-htx";
31const mstring html_mime="text/html";
32
33const mstring uri_tag="stat.URI";
34const mstring refer_tag="stat.REFER";
35const mstring parent_tag="stat.PARENT";
36const mstring mime_tag="stat.MIME";
37
38const mstring mod_tag="stat.MOD";
39const mstring mtime_tag="stat.LASTMOD";
40const mstring uid_tag="stat.UID";
41const mstring gid_tag="stat.GID";
42const mstring size_tag="stat.SIZE";
43
44const mstring alias_tag="stat.ALIAS";
45const mstring banner_tag="stat.BANNER";
46
47const mstring xclear_tag="stat.X.CLEAR";
48const mstring xcookie_tag="stat.X.COOKIE";
49const mstring domain_tag="stat.X.DOMAIN";
50const mstring user_tag="stat.X.USER";
51const mstring xcache_tag="stat.X.CACHE";
52
53const mstring xmod_tag="stat.XMOD";
54
55/////////////////////////////////////////////////////////////////
56
57TOK_IMPL(alias) {
58 mstring acc;
59 Env nenv(env,XSYSTEM,env.pwd);
60 acc=env.arg(0)->expr;
61 nenv.sloc(alias_tag,acc);
62}
63
64TOK_IMPL(banner) {
65 mstring acc1;
66 Env nenv(env,XSYSTEM,env.pwd);
67 swrite sw(acc1);
68 nenv.parse(sw,env.arg(0));
69 acc1+=' '; acc1+=env.arg(1)->expr;
70 nenv.sloc(banner_tag,acc1);
71}
72
73/////////////////////////////////////////////////////////////////
74
75TOK_IMPL(clearance) {
76 mstring acc;
77 Env nenv(env,XSYSTEM,env.pwd);
78 swrite sw(acc);
79 nenv.parse(sw,env.arg(0));
80 sref first,rest=acc;
81 while(Split(first,rest))
82 if(first==root_tag) THROW("user: ROOT group not allowed in clearance");
83 nenv.sloc(xclear_tag,acc);
84}
85
86TOK_IMPL(clearance_cookie) {
87 mstring acc1,acc2;
88 Env nenv(env,XSYSTEM,env.pwd);
89 swrite sw1(acc1);
90 nenv.parse(sw1,env.arg(0));
91 swrite sw2(acc2);
92 nenv.parse(sw2,env.arg(1));
93 acc1+=' '; acc1+=acc2;
94 nenv.sloc(xcookie_tag,acc1);
95}
96
97TOK_IMPL(clearance_domain) {
98 mstring acc;
99 Env nenv(env,XSYSTEM,env.pwd);
100 swrite sw(acc);
101 nenv.parse(sw,env.arg(0));
102 nenv.sloc(domain_tag,acc);
103}
104
105TOK_IMPL(clearance_user) {
106 mstring acc;
107 Env nenv(env,XSYSTEM,env.pwd);
108 swrite sw(acc);
109 nenv.parse(sw,env.arg(0));
110 nenv.sloc(user_tag,acc);
111}
112
113TOK_IMPL(cache) {
114 mstring acc;
115 Env nenv(env,XSYSTEM,env.pwd);
116 swrite sw(acc);
117 nenv.parse(sw,env.arg(0));
118 nenv.sloc(xcache_tag,acc);
119}
120
121/////////////////////////////////////////////////////////////////
122
123inline int reachable(const sref& uri)
124{
125 static const mstring sys_tag="/sys/";
126 static const mstring bin_tag="/bin/";
127 static const mstring htc_tag="/htc/";
128 static const mstring sccs_tag="/SCCS/";
129 static const mstring cvs_tag="/CVS/";
130 if(uri.right_last(sindex_tag)==sindex_tag) return 0;
131 if(uri.find(sys_tag)>=0) return 0;
132 if(uri.find(bin_tag)>=0) return 0;
133 if(uri.find(htc_tag)>=0) return 0;
134 if(uri.find(sccs_tag)>=0) return 0;
135 if(uri.find(cvs_tag)>=0) return 0;
136 return 1;
137}
138
139TOK_IMPL(staturi) {
140 struct stat fs; int ok=0;
141 mstring parent,refer,uri=env.URI(env[0]);
142 if(reachable(uri)) {
143 refer=uri; parent=refer.leftand_last('/');
144 if(refer.back()=='/') { refer+=index_tag; parent=parent.popb().leftand_last('/'); }
145 int s=stat(DocPath(env,refer).c_str(),&fs);
146 if(s>=0) {
147 if(fs.st_mode&24576) {
148 uri+='/'; refer=uri+index_tag;
149 s=stat(DocPath(env,refer).c_str(),&fs);
150 }
151 if(s>=0) {
152 const sref* pmime=file2mime(refer);
153 mstring mime=pmime?*pmime:http_mime_default;
154 mstring index=refer.leftand_last('/')+index_tag;
155
156 Env nenv(env);
157 nenv.aloc(uri_tag,uri);
158 nenv.aloc(refer_tag,refer);
159 nenv.aloc(parent_tag,parent);
160 nenv.aloc(mime_tag,mime);
161
162 nenv.aloc(mod_tag,itoa(fs.st_mode));
163 nenv.aloc(uid_tag,itoa(fs.st_uid));
164 nenv.aloc(gid_tag,itoa(fs.st_gid));
165 nenv.aloc(size_tag,itoa(fs.st_size));
166 nenv.aloc(mtime_tag,itoa(fs.st_mtime));
167
168 nenv.aloc(alias_tag,ms_empty);
169 nenv.aloc(banner_tag,ms_empty);
170
171 nenv.aloc(xclear_tag,root_tag);
172 nenv.aloc(xcookie_tag,ms_empty);
173 nenv.aloc(domain_tag,ms_empty);
174 nenv.aloc(user_tag,ms_empty);
175 nenv.aloc(xcache_tag,ms_empty);
176
177 nenv.aloc(xmod_tag,itoa(time(0)));
178
179 mstring buffer;
180 if(mime==htc_mime||mime==htx_mime||mime==html_mime) {
181 LoadBuffer(buffer,DocPath(nenv,refer));
182 try {
183 Env e(nenv,XINIT,refer);
184 mstream m;
185 e.parse(m,buffer);
186 }
187 catch(const merror_t& e) {
188 THROW(refer<<": "<<e.desc);
189 }
190 }
191 if(mime!=htc_mime&&nenv.gloc(xclear_tag)==root_tag) {
192 if(buffer.load(DocPath(nenv,index).c_str())>=0) {
193 try {
194 Env e(nenv,XINIT,index);
195 mstream m;
196 e.parse(m,buffer);
197 nenv.sloc(alias_tag,ms_empty);
198 nenv.sloc(banner_tag,ms_empty);
199 }
200 catch(const merror_t& e) {
201 THROW(index<<": "<<e.desc);
202 }
203 }
204 }
205 nenv.parse(out,env.arg(1));
206 ok=1;
207 }
208 }
209 }
210 if(!ok) env.parg(out,2);
211}
212
213/////////////////////////////////////////////////////////////////
214
215void envAddTree(tokmap& T)
216{
217 TOK_ADD(alias,"r",tok_t::INIT,
218 "%Set alias used in sitemap\n"
219 "%Syntax: \\alias{name}\n"
220 "%\n"
221 "%If set, the URI appears in the automatic tree system.\n"
222 );
223
224 TOK_ADD(banner,"rr",tok_t::INIT,
225 "%Set banner used in layout\n"
226 "%Syntax: \\banner{height}{body}\n"
227 "%\n"
228 "%If set in index file, all URI descendants will use it.\n"
229 );
230
231 ///////////////////////////////////////////////////////
232
233 TOK_ADD(clearance,"r",tok_t::INIT,
234 "%Set clearance\n"
235 "%Syntax: \\clearance{group list}\n"
236 "%\n"
237 "%A user must have clearance to all groups in order\n"
238 "%to get access.\n"
239 );
240 TOK_ADD(clearance_domain,"r",tok_t::INIT,
241 "%Restrict clearance to domain\n"
242 "%Syntax: \\clearance.domain{domain list}\n"
243 "%\n"
244 "%A user must have clearance to at least one domain\n"
245 "%in order to get access.\n"
246 );
247 TOK_ADD(clearance_cookie,"rr",tok_t::INIT,
248 "%Restrict by cookie\n"
249 "%Syntax: \\clearance.cookie{name}{value}\n"
250 "%\n"
251 "%A user must have the cookie set to get access.\n"
252 );
253 TOK_ADD(clearance_user,"r",tok_t::INIT,
254 "%Restrict by user\n"
255 "%Syntax: \\clearance.user{user list}\n"
256 "%\n"
257 "%A user must appear in the list in order to get access.\n"
258 );
259
260 ///////////////////////////////////////////////////////
261
262 TOK_ADD(cache,"r",tok_t::INIT,
263 "%Set cache time in seconds\n"
264 "%Syntax: \\cache{t}\n"
265 "%\n"
266 "%If set, normal output is cached for the given time.\n"
267 "%\n"
268 "%There are a number of advantages of caching, the most\n"
269 "%pronounced being server load. Appropriate cache time\n"
270 "%is crucial to get a smooth server.\n"
271 );
272
273 ///////////////////////////////////////////////////////
274
275 TOK_ADD(staturi,"xr?",tok_t::SYSONLY,
276 "%Retrieve STAT and INIT information for URI\n"
277 "%Syntax: \\staturi{uri}{body}<else>\n"
278 "%\n"
279 "%Do body if a reference to uri is found.\n"
280 "%In the body environment, the record stat. is set\n"
281 "%with the following variables:\n"
282 "%\n"
283 "%URI the canonized URI\n"
284 "%REFER the file uri it refers to\n"
285 "%PARENT the parent uri\n"
286 "%MOD the file mode bits (unix)\n"
287 "%UID the file uid (unix)\n"
288 "%GID the file gid (unix)\n"
289 "%SIZE the file size (unix)\n"
290 "%LASTMOD the file modification time (unix)\n"
291 "%MIME the MIME type\n"
292 "%ALIAS alias used in tree\n"
293 "%X.CLEAR clerarance\n"
294 "%X.COOKIE cookie clearance\n"
295 "%X.DOMAIN domain clearance\n"
296 "%X.USER user clearance\n"
297 "%X.CACHE cache time in seconds\n"
298 "%\n"
299 "%The X. variables are inherited from index.htc\n"
300 "%if X.CLEAR remains equal to ROOT after init.\n"
301 "%\n"
302 "%Unreachable directories: /sys/, /bin/, /htc/, /SCCS/ and /CVS/.\n"
303 );
304}
diff --git a/src/sh/user.cc b/src/sh/user.cc
new file mode 100644
index 0000000..94285ef
--- /dev/null
+++ b/src/sh/user.cc
@@ -0,0 +1,445 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <sh/htc.h>
21
22int allow(const sref& s,const sref& grp,time_t now,int rootok)
23{
24 if(grp.empty()) return 1;
25 int n=s.find(':');
26 sref a=s.left(n);
27 if(rootok>=0&&a==root_tag) return rootok;
28 else if(grp==root_tag||a!=grp) return 0;
29 n=(a=s.past(n,1)).find(':'); sref b=a.past(n,1); a=a.left(n);
30 return (a.empty()||atoi(a)<=now)&&(b.empty()||now<atoi(b));
31}
32
33////////////////////////////////////////////////////////////////////////
34
35user_t::user_t(const user_t& us) : list(user_tabs)
36{
37 for(int i=0;i<user_tabs;i++) list[i]=us.list[i];
38}
39
40void user_t::operator=(const user_t& us)
41{
42 list.resize(user_tabs);
43 for(int i=0;i<user_tabs;i++) list[i]=us.list[i];
44}
45
46void user_t::reset()
47{
48 list.resize(user_tabs);
49 uid()=itoa(0);
50 group()=itoa(0);
51 fail()=itoa(0);
52 pin().clear();
53 alias().clear();
54 email().clear();
55 name().clear();
56 last()=itoa(0);
57 lastin()=lastin_def;
58 access().clear();
59}
60
61int user_t::allow(const sref& grp,time_t now,int rootok)
62{
63 sref first,rest=access();
64 while(Split(first,rest)) if(::allow(first,grp,now,rootok)) return 1;
65 return 0;
66}
67
68int user_t::allow_list(const sref& grps,time_t now,int rootok)
69{
70 sref first,rest=grps;
71 while(Split(first,rest)) if(!allow(first,now,rootok)) return 0;
72 return 1;
73}
74
75void user_t::add(const sref& grp)
76{
77 sref first,rest=access();
78 while(Split(first,rest)) if(first.left_first(':')==grp.left_first(':')) return;
79 mstring clear=grp;
80 if(clear.find(':')<0) { clear+=':'; clear+=itoa(time(0)); }
81 if(access().nempty()) access()+=' '; access()+=clear;
82}
83
84void user_t::add_list(const sref& grps) {
85 sref first,rest=grps;
86 while(Split(first,rest)) add(first);
87}
88
89void user_t::rem(const sref& grp)
90{
91 mstring m;
92 sref first,rest=access();
93 while(Split(first,rest))
94 if(first.left_first(':')!=grp) { if(m.nempty()) m+=' '; m+=first; }
95 access()=m;
96}
97
98void user_t::rem_list(const sref& grps)
99{
100 sref first,rest=grps;
101 while(Split(first,rest)) rem(first);
102}
103
104////////////////////////////////////////////////////////////////////////
105
106static dbmap* GetDB(Env& env,const sref& name)
107{
108 dbref_t* p=(dbref_t*)env.toks->get(name);
109 if(!env.is_clear(p)||!p->is_dbref()) THROW("htc: could not find system db "<<name);
110 p->db.remap();
111 return &p->db;
112}
113
114static int FindUser(Env& env,const sref& name)
115{
116 dbmap* users=GetDB(env,USERS_tag);
117 for(int i=0;i<users->size();i++) {
118 if(users->at(i,user_alias)==name) return atoi(users->at(i,user_uid));
119 sref first,rest=users->at(i,user_email);
120 while(Split(first,rest)) if(eqn(first,name)) return atoi(users->at(i,user_uid));
121 }
122 return 0;
123}
124
125////////////////////////////////////////////////////////////////////////
126
127TOK_IMPL(setgroup) { Req(env)->group=First(env[0]); }
128TOK_IMPL(group) { out<<Req(env)->group; }
129
130TOK_IMPL(getgroups) {
131 dbmap* users=GetDB(env,USERS_tag);
132 mset m;
133 for(int i=0;i<users->size();i++) {
134 sref first,rest=users->at(i,user_access);
135 while(Split(first,rest)) m.insert(first.left_first(':'));
136 }
137 out<<m;
138}
139
140////////////////////////////////////////////////////////////////////////
141
142TOK_IMPL(getuser) {
143 out<<FindUser(env,env[0]);
144}
145
146TOK_IMPL(setuser) {
147 dbmap* users=GetDB(env,USERS_tag);
148 int row=users->Find(env[0]);
149 if(row>=0) users->Get(row,Req(env)->user.list);
150 else Req(env)->user.reset();
151}
152
153TOK_IMPL(remuser) {
154 dbmap* users=GetDB(env,USERS_tag);
155 int row=users->Find(env[0]);
156 if(row>=0) users->Rem(row);
157}
158
159TOK_IMPL(newuser) {
160 static const charset namends("*@.+");
161 user_t user;
162 sref first,rest=env[0];
163 Split(first,rest);
164 user.group()=first.left_first(':');
165 do user.add(first);
166 while(Split(first,rest));
167 user.pin()=Random(4);
168 user.email()=env[1];
169 rest=env[1]; while(Split(first,rest)) if(FindUser(env,first)) { out<<0; return; }
170 mstring tag,alias=env[1].left_first_of(namends);
171 while(FindUser(env,alias+tag)) tag=itoa(atoi(tag)+1);
172 user.alias()=alias+tag;
173 user.name()=env[2];
174 dbmap* users=GetDB(env,USERS_tag);
175 if(users->empty()) user.uid()=itoa(1);
176 else user.uid()=itoa(atoi(users->at(users->size()-1,user_uid))+1);
177 int row=users->Insert(user.list,1);
178 if(row<0) THROW("htc: could not add user - record not unique");
179 out<<user.uid();
180}
181
182//////////////////////////////////////////////////////////////////////////
183
184TOK_IMPL(user_id) { out<<Req(env)->user.uid(); }
185TOK_IMPL(user_group) { out<<Req(env)->user.group(); }
186TOK_IMPL(user_access) { out<<Req(env)->user.access(); }
187TOK_IMPL(user_clear) {
188 sref first,rest=Req(env)->user.access(); int n=0;
189 while(Split(first,rest)) { if(n++) out.put(' '); out<<first.left_first(':'); }
190}
191
192TOK_IMPL(user_fail) { out<<Req(env)->user.fail(); }
193TOK_IMPL(user_pin) { out<<Req(env)->user.pin(); }
194TOK_IMPL(user_alias) { out<<Req(env)->user.alias(); }
195TOK_IMPL(user_email) { out<<First(Req(env)->user.email()); }
196TOK_IMPL(user_emails) { out<<Req(env)->user.email(); }
197TOK_IMPL(user_name) { out<<Req(env)->user.name(); }
198TOK_IMPL(user_last) { out<<Req(env)->user.last(); }
199TOK_IMPL(user_lastin) { out<<Req(env)->user.lastin(); }
200
201//////////////////////////////////////////////////////////////////////////
202
203TOK_IMPL(user_group_set) { Req(env)->user.group()=env[0]; }
204TOK_IMPL(user_access_add) { Req(env)->user.add_list(env[0]); }
205TOK_IMPL(user_access_rem) { Req(env)->user.rem_list(env[0]); }
206TOK_IMPL(user_fail_set) { Req(env)->user.fail()=env[0]; }
207TOK_IMPL(user_pin_set) { Req(env)->user.pin()=env[0]; }
208TOK_IMPL(user_alias_set) { Req(env)->user.alias()=env[0]; }
209TOK_IMPL(user_emails_set) { Req(env)->user.email()=env[0]; }
210TOK_IMPL(user_name_set) { Req(env)->user.name()=env[0]; }
211TOK_IMPL(user_last_set) { Req(env)->user.last()=env[0]; }
212TOK_IMPL(user_lastin_set) { Req(env)->user.lastin()=env[0]; }
213
214//////////////////////////////////////////////////////////
215
216TOK_IMPL(user_update) {
217 htc_req* htc=Req(env);
218 int uid=atoi(htc->user.uid());
219 int who=FindUser(env,htc->user.alias());
220 if(who&&who!=uid) return;
221 sref first,rest=htc->user.email();
222 while(Split(first,rest)) {
223 who=FindUser(env,first);
224 if(who&&who!=uid) return;
225 }
226 dbmap* users=GetDB(env,USERS_tag);
227 int row=users->Find(htc->user.uid());
228 if(row>=0) users->Set(row,htc->user.list);
229}
230
231//////////////////////////////////////////////////////////
232
233TOK_IMPL(su) {
234 htc_req* htc=Req(env);
235 user_t tmp(htc->user);
236 dbmap* users=GetDB(env,USERS_tag);
237 int row=users->Find(env[0]);
238 if(row>=0) {
239 try {
240 users->Get(row,htc->user.list);
241 env.parg(out,1);
242 htc->user=tmp;
243 }
244 catch(...) {
245 htc->user=tmp;
246 throw;
247 }
248 }
249 else env.parg(out,2);
250}
251
252//////////////////////////////////////////////////////////
253
254void envAddUser(tokmap& T) throw(merror_t)
255{
256 TOK_ADD(setgroup,"x",tok_t::SYSONLY,
257 "%Set current group\n"
258 "%Syntax: \\setgroup{group}\n"
259 "%\n"
260 "%Nop function; only for logging and structure.\n"
261 );
262 TOK_ADD(group,"",tok_t::PUBLIC,
263 "%Get current group\n"
264 "%Syntax: \\group\n"
265 "%\n"
266 "%Nop function; only for logging and structure.\n"
267 );
268
269 TOK_ADD(getgroups,"",tok_t::PUBLIC,
270 "%Get all groups\n"
271 "%Syntax: \\getgroups\n"
272 "%\n"
273 "%Scans users db for all groups used\n"
274 );
275
276 ///////////////////////////////////////////////////
277
278 TOK_ADD(getuser,"x",tok_t::SYSONLY,
279 "%Get user ID\n"
280 "%Syntax: \\getuser{alias/email}\n"
281 "%\n"
282 "%Returns the uid if found, or zero if not found\n"
283 );
284 TOK_ADD(setuser,"x",tok_t::SYSONLY,
285 "%Set current user\n"
286 "%Syntax: \\setuser{uid}\n"
287 );
288 TOK_ADD(remuser,"x",tok_t::SYSONLY,
289 "%Remove user\n"
290 "%Syntax: \\remuser{uid}\n"
291 );
292 TOK_ADD(newuser,"xxx",tok_t::SYSONLY,
293 "%Add a new user\n"
294 "%Syntax: \\newuser{clear}{email}{name}\n"
295 "%\n"
296 "%Returns the new uid if successful, otherwise zero.\n"
297 );
298
299 ///////////////////////////////////////////////////
300
301 TOK_ADD(user_id,"",tok_t::PUBLIC,
302 "%Get uid of current user\n"
303 "%Syntax: \\user.id\n"
304 );
305 TOK_ADD(user_group,"",tok_t::PUBLIC,
306 "%Get group of current user\n"
307 "%Syntax: \\user.group\n"
308 );
309 TOK_ADD(user_access,"",tok_t::PUBLIC,
310 "%Get access of current user\n"
311 "%Syntax: \\user.access\n"
312 );
313 TOK_ADD(user_clear,"",tok_t::PUBLIC,
314 "%Get clearance of current user\n"
315 "%Syntax: \\user.clear\n"
316 "%\n"
317 "%This is a compiled list, without the time info.\n"
318 );
319 TOK_ADD(user_fail,"",tok_t::PUBLIC,
320 "%Get fail number of current user\n"
321 "%Syntax: \\user.fail\n"
322 );
323 TOK_ADD(user_pin,"",tok_t::SYSONLY,
324 "%Get pin of current user\n"
325 "%Syntax: \\user.pin\n"
326 );
327 TOK_ADD(user_alias,"",tok_t::PUBLIC,
328 "%Get alias of current user\n"
329 "%Syntax: \\user.alias\n"
330 );
331 TOK_ADD(user_email,"",tok_t::PUBLIC,
332 "%Get email of current user\n"
333 "%Syntax: \\user.email\n"
334 "%\n"
335 "%Note that the email list may contain several addresses;\n"
336 "%this function returns the first in the list.\n"
337 );
338 TOK_ADD(user_emails,"",tok_t::PUBLIC,
339 "%Get all email addresses of current user\n"
340 "%Syntax: \\user.emails\n"
341 );
342 TOK_ADD(user_name,"",tok_t::PUBLIC,
343 "%Get name of current user\n"
344 "%Syntax: \\user.name\n"
345 );
346 TOK_ADD(user_last,"",tok_t::PUBLIC,
347 "%Get last time logged in of current user\n"
348 "%Syntax: \\user.last\n"
349 );
350 TOK_ADD(user_lastin,"",tok_t::PUBLIC,
351 "%Get last IP address of current user\n"
352 "%Syntax: \\user.lastin\n"
353 );
354
355 ///////////////////////////////////////////////////
356
357 TOK_ADD(user_group_set,"x",tok_t::SYSONLY,
358 "%Set group of current user\n"
359 "%Syntax: \\user.group.set{group}\n"
360 "%\n"
361 "%Note that the changes take effect after a \\user.update\n"
362 );
363 TOK_ADD(user_access_add,"x",tok_t::SYSONLY,
364 "%Add access to current user\n"
365 "%Syntax: \\user.access.add{group:start:stop}\n"
366 "%\n"
367 "%The :start:stop part may be omitted, in which case\n"
368 "%a start value of now, and a stop value of nil is set.\n"
369 "%\n"
370 "%In case of several group strings, they are all added.\n"
371 "%\n"
372 "%Note that the changes take effect after a \\user.update\n"
373 );
374 TOK_ADD(user_access_rem,"x",tok_t::SYSONLY,
375 "%Remove access from current user\n"
376 "%Syntax: \\user.access.rem{group}\n"
377 "%\n"
378 "%In case of several groups, they are all removed.\n"
379 "%\n"
380 "%Note that the changes take effect after a \\user.update\n"
381 );
382 TOK_ADD(user_fail_set,"x",tok_t::SYSONLY,
383 "%Set fail number of current user\n"
384 "%Syntax: \\user.fail.set{fail}\n"
385 "%\n"
386 "%Note that the changes take effect after a \\user.update\n"
387 );
388 TOK_ADD(user_pin_set,"x",tok_t::SYSONLY,
389 "%Set pin of current user\n"
390 "%Syntax: \\user.pin.set{pin}\n"
391 "%\n"
392 "%Note that the changes take effect after a \\user.update\n"
393 );
394 TOK_ADD(user_alias_set,"x",tok_t::SYSONLY,
395 "%Set alias of current user\n"
396 "%Syntax: \\user.alias.set{alias}\n"
397 "%\n"
398 "%Note that the changes take effect after a \\user.update\n"
399 );
400 TOK_ADD(user_emails_set,"x",tok_t::SYSONLY,
401 "%Set all email addresses of current user\n"
402 "%Syntax: \\user.emails.set{emails}\n"
403 "%\n"
404 "%Note that the changes take effect after a \\user.update\n"
405 );
406 TOK_ADD(user_name_set,"x",tok_t::SYSONLY,
407 "%Set name of current user\n"
408 "%Syntax: \\user.name.set{name}\n"
409 "%\n"
410 "%Note that the changes take effect after a \\user.update\n"
411 );
412 TOK_ADD(user_last_set,"x",tok_t::SYSONLY,
413 "%Set last time logged in of current user\n"
414 "%Syntax: \\user.last.set{last}\n"
415 "%\n"
416 "%Note that the changes take effect after a \\user.update\n"
417 );
418 TOK_ADD(user_lastin_set,"x",tok_t::SYSONLY,
419 "%Set last IP address of current user\n"
420 "%Syntax: \\user.lastin.set{addr}\n"
421 "%\n"
422 "%Note that the changes take effect after a \\user.update\n"
423 );
424
425 ///////////////////////////////////////////////////
426
427 TOK_ADD(user_update,"",tok_t::SYSONLY,
428 "%Update the current user\n"
429 "%Syntax: \\user.update\n"
430 "%\n"
431 "%All changes a synchronous and immediately available.\n"
432 );
433
434 ///////////////////////////////////////////////////
435
436 TOK_ADD(su,"xr?",tok_t::SYSONLY,
437 "%Set user temporary\n"
438 "%Syntax: \\su{uid}{body}<else>\n"
439 "%\n"
440 "%If set successfully, evaluates body, otherwise <else>.\n"
441 );
442
443 ///////////////////////////////////////////////////
444
445}
diff --git a/src/sh/user.h b/src/sh/user.h
new file mode 100644
index 0000000..cc00e21
--- /dev/null
+++ b/src/sh/user.h
@@ -0,0 +1,92 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef USERH
21#define USERH
22
23#include <lang/env.h>
24#include <mt/lookup.h>
25
26/////////////////////////////////////////////////////////
27
28const mstring root_tag="ROOT";
29const mstring lastin_def="0.0.0.0";
30
31const mstring USERS_tag="USERS";
32const mstring PREFS_tag="PREFS";
33const mstring TREE_tag="TREE";
34
35const int user_tabs=10,user_uid=0,user_alias=4,user_email=5,user_access=9;
36const mstring user_tab[user_tabs]={
37 "UID","GROUP","FAIL","PIN","ALIAS","EMAIL","NAME","LAST","LASTIN","ACCESS"
38};
39
40const int prefs_tabs=8;
41const mstring prefs_tab[prefs_tabs]={
42 "ID","EXT","ROOM","URL","POSIT","NOTE","ABSTRACT","LASTMOD"
43};
44
45const int tree_tabs=17;
46const mstring tree_tab[tree_tabs]={
47 "URI","REFER","PARENT","MIME",
48 "MOD","UID","GID","SIZE","LASTMOD",
49 "ALIAS","BANNER",
50 "X.CLEAR","X.COOKIE","X.DOMAIN","X.USER","X.CACHE",
51 "XMOD"
52};
53
54int allow(const sref& s,const sref& grp,time_t now,int rootok=0);
55
56struct user_t {
57 spile list;
58
59 user_t() : list(user_tabs) {}
60 user_t(const user_t& us);
61
62 void operator=(const user_t&);
63
64 mstring& uid() { return list[0]; }
65 mstring& group() { return list[1]; }
66 mstring& fail() { return list[2]; }
67 mstring& pin() { return list[3]; }
68 mstring& alias() { return list[4]; }
69 mstring& email() { return list[5]; }
70 mstring& name() { return list[6]; }
71 mstring& last() { return list[7]; }
72 mstring& lastin() { return list[8]; }
73 mstring& access() { return list[9]; }
74
75 void reset();
76 int allow(const sref& grp,time_t now,int rootok=0);
77 int allow_list(const sref& grps,time_t now,int rootok=0);
78 // rootok<0 -> ignore special root handling (new; should not interfere)
79 // rootok==0 -> root not allowed here
80 // rootok>0 -> root always allowed here
81
82 void add(const sref& grp);
83 void add_list(const sref& grps);
84 void rem(const sref& grp);
85 void rem_list(const sref& grps);
86};
87
88/////////////////////////////////////////////////////////
89
90void envAddUser(tokmap& T) throw(merror_t);
91
92#endif
diff --git a/src/test/EXPECTED.mt b/src/test/EXPECTED.mt
new file mode 100644
index 0000000..57ac1b2
--- /dev/null
+++ b/src/test/EXPECTED.mt
@@ -0,0 +1,17 @@
1more strange asdf
2
3more strange asdf
4 Hello! this is appending 4 to string
5
6********
7********
8Error test: 0
9hello 4 once more
10********
111
12********
136
14[asdf]
15********
16Got [hello world!]
17Got []
diff --git a/src/test/EXPECTED.ops b/src/test/EXPECTED.ops
new file mode 100644
index 0000000..f6bb64a
--- /dev/null
+++ b/src/test/EXPECTED.ops
@@ -0,0 +1 @@
403.428793492735
diff --git a/src/test/cmd.hexp b/src/test/cmd.hexp
new file mode 100644
index 0000000..de16627
--- /dev/null
+++ b/src/test/cmd.hexp
@@ -0,0 +1,4 @@
11+2,
2a=6,
31+a,
4exp a
diff --git a/src/test/run.sh b/src/test/run.sh
new file mode 100755
index 0000000..01591bf
--- /dev/null
+++ b/src/test/run.sh
@@ -0,0 +1,6 @@
1#!/bin/sh
2bin=`which $0`; cd `dirname $bin`
3echo "mt:"
4../tmp/bin/mt/test | diff -a EXPECTED.mt -
5echo "ops:"
6../tmp/bin/ops/test cmd.hexp | diff -a EXPECTED.ops -