1 |
dpavlin |
237 |
/* |
2 |
|
|
this file composed by Klaus Ripke from the iAPI files by Robert Janusz. |
3 |
|
|
this is the test app "ix.c" with all the includes slurped in, |
4 |
|
|
see // #include "isomething.c" |
5 |
|
|
|
6 |
|
|
you may run this with: |
7 |
|
|
cp iAPI.txt iAPI.c |
8 |
|
|
gcc iAPI.c |
9 |
|
|
./a.out <dbpath> |
10 |
|
|
*/ |
11 |
|
|
|
12 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
13 |
|
|
iAPI software: The Example of ISIS (UNIX v.3) Database Handle |
14 |
|
|
Copyright (C) 2000 by Robert Janusz |
15 |
|
|
E-mail: rj@jezuici.krakow.pl |
16 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
17 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
18 |
|
|
|
19 |
|
|
This program is free software; you can redistribute it and/or |
20 |
|
|
modify it under the terms of the GNU General Public License |
21 |
|
|
as published by the Free Software Foundation. |
22 |
|
|
|
23 |
|
|
This program is distributed in the hope that it will be useful, |
24 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 |
|
|
GNU General Public License for more details. |
27 |
|
|
|
28 |
|
|
You should have received a copy of the GNU General Public License |
29 |
|
|
along with this program; if not, write to the Free Software |
30 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
31 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
32 |
|
|
|
33 |
|
|
// Linux gcc Compiler conventions ! |
34 |
|
|
|
35 |
|
|
#include <stdio.h> |
36 |
|
|
#include <stdlib.h> |
37 |
|
|
#include <stdarg.h> |
38 |
|
|
#include <string.h> |
39 |
|
|
|
40 |
|
|
// Global variables +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
41 |
|
|
|
42 |
|
|
static |
43 |
|
|
char DBpath [71]; |
44 |
|
|
char UpCase [256]; |
45 |
|
|
|
46 |
|
|
#define NFIND 3 // let's keep it for future |
47 |
|
|
|
48 |
|
|
#define PACKED __attribute__((packed)) // it shoud work on Linux gcc ;-) |
49 |
|
|
|
50 |
|
|
// #include "idef.c" |
51 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
52 |
|
|
iAPI software: The Type Definitions for Unix-ISIS databases |
53 |
|
|
Copyright (C) 2000 by Robert Janusz |
54 |
|
|
E-mail: rj@jezuici.krakow.pl |
55 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
56 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
57 |
|
|
|
58 |
|
|
This program is free software; you can redistribute it and/or |
59 |
|
|
modify it under the terms of the GNU General Public License |
60 |
|
|
as published by the Free Software Foundation. |
61 |
|
|
|
62 |
|
|
This program is distributed in the hope that it will be useful, |
63 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
64 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
65 |
|
|
GNU General Public License for more details. |
66 |
|
|
|
67 |
|
|
You should have received a copy of the GNU General Public License |
68 |
|
|
along with this program; if not, write to the Free Software |
69 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
70 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
71 |
|
|
|
72 |
|
|
// gcc Linux Compiler conventions ! |
73 |
|
|
// *** ONLY UNIX ISIS = the difference between DOS/UNIX structures |
74 |
|
|
|
75 |
|
|
// *************************** TYPE DEFINITIONS ***************************** |
76 |
|
|
|
77 |
|
|
// Cross Reference File XRF structure +++++++++++++++++++++++++++++++++++++++ |
78 |
|
|
|
79 |
|
|
typedef /* Packed */ struct // /* Packed */ and order are necessary for block reading |
80 |
|
|
{ |
81 |
|
|
long int xpos PACKED; |
82 |
|
|
// Block nr: 1, 2...; < 0: last block |
83 |
|
|
long int xrec [127] PACKED; |
84 |
|
|
// References to Master File records... |
85 |
|
|
// xrec [...] = 2048 *xrmfb [21 bit] & xrmfp [11 bit] |
86 |
|
|
// rec. deleted log. < 0 & > 0 (restore: -xrmfb) |
87 |
|
|
// rec. deleted phis. =-1 & = 0 (ref@MST.ctrl) |
88 |
|
|
// rec. does not exist = 0 & = 0 |
89 |
|
|
// new rec. to invert bit 1024 = 1 |
90 |
|
|
// rec. edited to inv. (add & del post.) bit 512 = 1 |
91 |
|
|
} |
92 |
|
|
xrfBlock; |
93 |
|
|
|
94 |
|
|
// Master File (MST) record structures... +++++++++++++++++++++++++++++++++++ |
95 |
|
|
|
96 |
|
|
typedef /* Packed */ struct // The first record in Master File |
97 |
|
|
{ |
98 |
|
|
long int ctlmfn PACKED // Always 0 |
99 |
|
|
, nxtmfn PACKED // Next Master File Number |
100 |
|
|
, nxtmfb PACKED; // Next block in Master File, the 1st has 1 |
101 |
|
|
short int nxtmfp PACKED // Next position in the last block |
102 |
|
|
, mftype PACKED; // 0 for user's bases; 1 for messages |
103 |
|
|
long int reccnt PACKED // Reserved for future |
104 |
|
|
, mfcxx1 PACKED // Reserved for future |
105 |
|
|
, mfcxx2 PACKED // LAN, > 0: inversion, update not possible |
106 |
|
|
, mfcxx3 PACKED; // LAN, = 1: exists exclusive user |
107 |
|
|
} |
108 |
|
|
mstControl; |
109 |
|
|
|
110 |
|
|
typedef /* Packed */ struct // Fixed part of record header that must be... |
111 |
|
|
{ // included in the same block; |
112 |
|
|
// the header can begin only on 0, 2, 4...498 |
113 |
|
|
long int mfn PACKED; // MFN number |
114 |
|
|
short int mfrl PACKED; // Length of record (allways eaven)... |
115 |
|
|
// LAN: < 0 ==> record blocked |
116 |
|
|
long int mfbwb PACKED; // Block Pointer | If the record waits for inv... |
117 |
|
|
short int mfbwp PACKED; // Position Pointer | ...ref. to old location |
118 |
|
|
// mfbwb, mfbwp: = 0 at creation; |
119 |
|
|
// after modif. = ref to the old record. |
120 |
|
|
// xrmfp bit 1024 = 1 at creation |
121 |
|
|
// (= waits to be inverted); |
122 |
|
|
// xrmfp bit 512 = 1 at edit |
123 |
|
|
// (=waits to be inv. & delete old references) |
124 |
|
|
} |
125 |
|
|
mstHdrFix; |
126 |
|
|
|
127 |
|
|
typedef /* Packed */ struct |
128 |
|
|
{ |
129 |
|
|
short int base PACKED // Position of data fields in the record |
130 |
|
|
, nvf PACKED // Number of fields in the record |
131 |
|
|
, status PACKED; // 0 = active, 1 = deleted logicaly (- xrfb < 0) |
132 |
|
|
} |
133 |
|
|
mstHdrTxt; |
134 |
|
|
|
135 |
|
|
typedef /* Packed */ struct |
136 |
|
|
{ |
137 |
|
|
mstHdrFix mhf PACKED; // This header is allways in MST file block |
138 |
|
|
mstHdrTxt mht PACKED; |
139 |
|
|
} |
140 |
|
|
RecHeaders; |
141 |
|
|
|
142 |
|
|
typedef /* Packed */ struct // Index for every field in the record |
143 |
|
|
{ // dimension = 6 *nvf; base = 18 + 6 *nvf |
144 |
|
|
short int tag PACKED // Label of the field |
145 |
|
|
, pos PACKED // Position of the first char in data part: 0, 1... |
146 |
|
|
, len PACKED; // Length of the field |
147 |
|
|
} |
148 |
|
|
mstIndex; |
149 |
|
|
|
150 |
|
|
// Inverted File structures +++++++++++++++++++++++++++++++++++++++++++++++++ |
151 |
|
|
|
152 |
|
|
// Control File (CNT) structure.............................................. |
153 |
|
|
|
154 |
|
|
typedef /* Packed */ struct |
155 |
|
|
{ |
156 |
|
|
short int idtype PACKED // B*tree type; 1 = N01/L01, 2 = N02/L02 |
157 |
|
|
, ordn PACKED // = 5; a half of size of key-record in N0x |
158 |
|
|
, ordf PACKED // = 5; a half of size of key-record in L0x |
159 |
|
|
, n PACKED // = 15; number of buffers for nodes |
160 |
|
|
, k PACKED // = 5; number of buffers for 1st index level (k < n) |
161 |
|
|
, lev PACKED; // Current number of levels in index; -1: no N0x |
162 |
|
|
long int posrx PACKED // Reference to the root in N0x |
163 |
|
|
, nmaxpos PACKED // Next record in N0x |
164 |
|
|
, fmaxpos PACKED; // Next record in L0x |
165 |
|
|
short int abnormal PACKED; // 0: N0x has only the root |
166 |
|
|
} |
167 |
|
|
cntBlock; |
168 |
|
|
|
169 |
|
|
// Index of Dictionary (N0x) structures...................................... |
170 |
|
|
|
171 |
|
|
typedef /* Packed */ struct |
172 |
|
|
{ |
173 |
|
|
long int pos PACKED; // Number of record |
174 |
|
|
short int ock PACKED // Number of active keys in the record: 1, 2, 3...2*ordn |
175 |
|
|
, it PACKED; // B*tree type |
176 |
|
|
} |
177 |
|
|
nodeHeader; |
178 |
|
|
|
179 |
|
|
typedef /* Packed */ struct |
180 |
|
|
{ |
181 |
|
|
char key [10] PACKED; |
182 |
|
|
long int ref PACKED; // > 0: reference to next node; |
183 |
|
|
// < 0: ref. to leaf: idx [1st].key = key |
184 |
|
|
// = 0: inactive |
185 |
|
|
} |
186 |
|
|
nodeIndex1; |
187 |
|
|
|
188 |
|
|
typedef /* Packed */ struct |
189 |
|
|
{ |
190 |
|
|
char key [30] PACKED; |
191 |
|
|
long int ref PACKED; |
192 |
|
|
} |
193 |
|
|
nodeIndex2; |
194 |
|
|
|
195 |
|
|
typedef /* Packed */ struct |
196 |
|
|
{ |
197 |
|
|
nodeHeader hdr PACKED; |
198 |
|
|
nodeIndex1 idx [10] PACKED; // Vector of 2*ordn elements |
199 |
|
|
} |
200 |
|
|
nodeBlock1; |
201 |
|
|
|
202 |
|
|
typedef /* Packed */ struct |
203 |
|
|
{ |
204 |
|
|
nodeHeader hdr PACKED; |
205 |
|
|
nodeIndex2 idx [10] PACKED; // Vector of 2*ordn elements |
206 |
|
|
} |
207 |
|
|
nodeBlock2; |
208 |
|
|
|
209 |
|
|
typedef /* Packed */ union |
210 |
|
|
{ |
211 |
|
|
nodeBlock1 nb1 PACKED; |
212 |
|
|
nodeBlock2 nb2 PACKED; |
213 |
|
|
} |
214 |
|
|
nodeBlock; |
215 |
|
|
|
216 |
|
|
// Leaf File (L0x) structures (all index terms).............................. |
217 |
|
|
|
218 |
|
|
typedef /* Packed */ struct |
219 |
|
|
{ |
220 |
|
|
long int pos PACKED; // Number of leaf record: 1, 2... |
221 |
|
|
short int ock PACKED // Number of active keys in the record: 1..2*ordf |
222 |
|
|
, it PACKED; // = 1 for L01; = 2 for L02 |
223 |
|
|
long int ps PACKED; // Next record in the order: key [ock] < ps^ idx [1st].key |
224 |
|
|
} |
225 |
|
|
leafHeader; |
226 |
|
|
|
227 |
|
|
typedef /* Packed */ struct |
228 |
|
|
{ |
229 |
|
|
char key [10] PACKED; |
230 |
|
|
short int xxx PACKED; // *** ONLY UNIX ISIS; |
231 |
|
|
long int infb PACKED // Reference to IFP segment *** != ISIS.MANUAL *** |
232 |
|
|
, infp PACKED; |
233 |
|
|
} |
234 |
|
|
leafKey1; |
235 |
|
|
|
236 |
|
|
typedef /* Packed */ struct |
237 |
|
|
{ |
238 |
|
|
char key [30] PACKED; |
239 |
|
|
short int xxx PACKED; // *** ONLY UNIX ISIS; |
240 |
|
|
long int infb PACKED // Reference to IFP segment *** != ISIS.MANUAL *** |
241 |
|
|
, infp PACKED; |
242 |
|
|
} |
243 |
|
|
leafKey2; |
244 |
|
|
|
245 |
|
|
typedef /* Packed */ struct |
246 |
|
|
{ |
247 |
|
|
leafHeader hdr PACKED; |
248 |
|
|
leafKey1 idx [10] PACKED; // 2*ordf keys |
249 |
|
|
} |
250 |
|
|
leafBlock1; |
251 |
|
|
|
252 |
|
|
typedef /* Packed */ struct |
253 |
|
|
{ |
254 |
|
|
leafHeader hdr PACKED; |
255 |
|
|
leafKey2 idx [10] PACKED; // 2*ordf keys |
256 |
|
|
} |
257 |
|
|
leafBlock2; |
258 |
|
|
|
259 |
|
|
typedef /* Packed */ union |
260 |
|
|
{ |
261 |
|
|
leafBlock1 lb1 PACKED; |
262 |
|
|
leafBlock2 lb2 PACKED; |
263 |
|
|
} |
264 |
|
|
leafBlock; |
265 |
|
|
|
266 |
|
|
// Inverted File Posting structures.......................................... |
267 |
|
|
// ordained postings organized in segments: Index --> Master File |
268 |
|
|
|
269 |
|
|
typedef /* Packed */ struct |
270 |
|
|
{ |
271 |
|
|
long int ifblk PACKED // Number of block |
272 |
|
|
, ifrec [127] PACKED; // Vector of long int *** != ISIS.MANUAL *** |
273 |
|
|
// In 1st block ifrec [1st/2nd] = next pos. in IFP |
274 |
|
|
} |
275 |
|
|
ifpBlock; |
276 |
|
|
|
277 |
|
|
typedef /* Packed */ struct // This header and 1st posting - always in IFP block |
278 |
|
|
{ |
279 |
|
|
long int ifpnxtb PACKED // Pointer to the next segment: 1, 2... | = 0: last seg. |
280 |
|
|
, ifpnxtp PACKED // 0, 1... | = 0: last seg. |
281 |
|
|
, ifptotp PACKED // Tot. number of postings (o.k. only in the 1st segment) |
282 |
|
|
// = Sum (segment=1, nseg; ifpsegp) |
283 |
|
|
, ifpsegp PACKED // Number of postings in this segment |
284 |
|
|
, ifpsegc PACKED; // Max. number of postings in this segment (<= 32768) |
285 |
|
|
} |
286 |
|
|
ifpHeader; |
287 |
|
|
|
288 |
|
|
// ifpHeader & 1st ifpPosting always in the same ifpBlock |
289 |
|
|
// Postings in Segment are always in chain of IFP blocks |
290 |
|
|
|
291 |
|
|
typedef /* Packed */ struct // Stored left-->right + 0 --> 8 char |
292 |
|
|
{ |
293 |
|
|
long int pmfn PACKED; // First 3 bytes --> Master File |
294 |
|
|
short int ptag PACKED; // Field ident - according to File Selection Table (FST) |
295 |
|
|
char pocc PACKED; // Number of occurence of the field |
296 |
|
|
short int pcnt PACKED; // Counter of the termin inside the field |
297 |
|
|
} |
298 |
|
|
ifpPosting; |
299 |
|
|
|
300 |
|
|
typedef struct |
301 |
|
|
{ |
302 |
|
|
int opened; // Which files are opened (bit spec.)... |
303 |
|
|
FILE *mst; // 1 |
304 |
|
|
FILE *xrf; // 2 |
305 |
|
|
FILE *ifp; // 4 |
306 |
|
|
FILE *n01; // 8 |
307 |
|
|
FILE *l01; // 16 |
308 |
|
|
FILE *n02; // 32 |
309 |
|
|
FILE *l02; // 64 |
310 |
|
|
mstControl mctrl; // MST ctrl record |
311 |
|
|
cntBlock cnt1, cnt2; // Inv. Files ctrl records |
312 |
|
|
long int ibm, ipm; // IFP new Segment Bock/Pos |
313 |
|
|
char name [72]; // Database name |
314 |
|
|
} |
315 |
|
|
BaseCtrl; |
316 |
|
|
|
317 |
|
|
typedef struct // This structer must be allways corelated with BaseCtrl |
318 |
|
|
{ |
319 |
|
|
char st [31]; // Max. string to find |
320 |
|
|
short int v; // Field to find; 0: all fields |
321 |
|
|
short int it; // Type of B*Tree <== strlen (st) |
322 |
|
|
leafBlock lbl; // Block L0x with index terms |
323 |
|
|
short int ilk; // Position of term in lbl...idx |
324 |
|
|
char *term; // The term in lbl...idx |
325 |
|
|
long int ib, ip; // Number of block/position for IFP |
326 |
|
|
ifpBlock ibl; // Block IFP with posting/s |
327 |
|
|
ifpHeader ihd; // Header for Segment of postings |
328 |
|
|
long int iiseg; // Number of posting in current Segment (index) |
329 |
|
|
long int iitot; // Number of posting in total (index) |
330 |
|
|
long int iall; // Number of posting in all Segments |
331 |
|
|
char *ipst; // Ref. to last posting string [8 chars] |
332 |
|
|
cntBlock *cntr; // BaseCtrl.cntr1/2 <== it |
333 |
|
|
FILE *n0x; // N01 or N02 <== it, = BaseCtrl.n0x |
334 |
|
|
FILE *l0x; // L01 or L02 <== it, = BaseCtrl.l0x |
335 |
|
|
} |
336 |
|
|
TableQuery; |
337 |
|
|
|
338 |
|
|
#define RECLENGTH 8192 |
339 |
|
|
|
340 |
|
|
typedef union |
341 |
|
|
{ |
342 |
|
|
char buf [RECLENGTH]; |
343 |
|
|
RecHeaders hdrs; |
344 |
|
|
} |
345 |
|
|
RecCtrl; |
346 |
|
|
|
347 |
|
|
// *** MAIN DATABASE FILE RELATIONS (MST <--> XRF) *** |
348 |
|
|
// 1 2 3 |
349 |
|
|
// MST |-mblk-|-mblk-|-mblk-|-mblk-|-mblk-|-mblk-|-mblk-|-mblk-|... |
350 |
|
|
// ctrl |----record----| |
351 |
|
|
// |--->| |
352 |
|
|
// 1 2 3 | pointer: B/P (P in [0, 2, 4... 498]) |
353 |
|
|
// XRF |-xblk-|-xblk-|-xblk-|... |
354 |
|
|
// MFN= 1... 128... 255... |
355 |
|
|
// Record |-->-pos->--| |
356 |
|
|
// |-mhf-mht-|-idx[1]...idx[nvf]-|---text...---| |
357 |
|
|
// |-------------- record buffer --------------| |
358 |
|
|
|
359 |
|
|
// *** INVERTED FILE RELATIONS (N0x <--> L0x <-->IFP) *** |
360 |
|
|
// N0x |-nbl-|-nbl-|-nbl-|-nbl-|-nbl-|-nbl-|... |
361 |
|
|
// -->-root->-| |-->--next-->--| |->-->-| r<0 |
362 |
|
|
// | |
363 |
|
|
// L0x |--lbl--|--lbl--|--lbl--|--lbl--|--lbl--|--lbl--|... |
364 |
|
|
// | |
365 |
|
|
// |-<--------------<-------------<-| r<0 |
366 |
|
|
// *** POSTING *** | |
367 |
|
|
// IFP |---ibl---|---ibl---|---ibl---|---ibl---|---ibl---|---ibl---|... |
368 |
|
|
// |next |-ihd-|---Segment---| |-ihd-|---Segment---| |
369 |
|
|
// |Seg. |-->------>------>-next->--| |||... |
370 |
|
|
// MFN... |
371 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
372 |
|
|
|
373 |
|
|
// #include "idef.c" |
374 |
|
|
|
375 |
|
|
// Let's specify non int header ;-) just to keep order |
376 |
|
|
|
377 |
|
|
void ShowRec (RecCtrl *rc); |
378 |
|
|
void setQuery (BaseCtrl *bc, TableQuery *tq, char *sx, short int fld); |
379 |
|
|
void isis (); |
380 |
|
|
|
381 |
|
|
// #include "iutil.c" |
382 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
383 |
|
|
iAPI software: The UTIL procedures for Unix-ISIS databases |
384 |
|
|
Copyright (C) 2000 by Robert Janusz |
385 |
|
|
E-mail: rj@jezuici.krakow.pl |
386 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
387 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
388 |
|
|
|
389 |
|
|
This program is free software; you can redistribute it and/or |
390 |
|
|
modify it under the terms of the GNU General Public License |
391 |
|
|
as published by the Free Software Foundation. |
392 |
|
|
|
393 |
|
|
This program is distributed in the hope that it will be useful, |
394 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
395 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
396 |
|
|
GNU General Public License for more details. |
397 |
|
|
|
398 |
|
|
You should have received a copy of the GNU General Public License |
399 |
|
|
along with this program; if not, write to the Free Software |
400 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
401 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
402 |
|
|
|
403 |
|
|
// gcc Linux Compiler conventions ! |
404 |
|
|
// *** ONLY UNIX ISIS = the difference between DOS/UNIX structures |
405 |
|
|
|
406 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
407 |
|
|
|
408 |
|
|
int ReadMem (void *ptr, FILE *f, long int nr, long int size) |
409 |
|
|
{ // Read "nr"'s block of size "size" from file "f" into "ptr"... |
410 |
|
|
if (fseek (f, nr * size, SEEK_SET) != 0) return (-1); |
411 |
|
|
if (fread (ptr, size, 1, f) == 0) return (-2); |
412 |
|
|
return (0); // O.K. |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
416 |
|
|
|
417 |
|
|
void doUpcase (char *s, char *st, int slen) |
418 |
|
|
{ int i; |
419 |
|
|
for (i = 0; i < slen; i++) |
420 |
|
|
{ if (i < strlen (st)) s [i] = UpCase [(int) st [i]]; else s [i] = ' '; } |
421 |
|
|
s [slen] = 0; |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
425 |
|
|
|
426 |
|
|
int sComp (char *s1, char *s2, int len) |
427 |
|
|
{ int i; |
428 |
|
|
for (i = 0; i < len; i++) |
429 |
|
|
{ if (s1 [i] > s2 [i]) return (1); // .gt. |
430 |
|
|
if (s1 [i] < s2 [i]) return (-1); // .lt. |
431 |
|
|
} |
432 |
|
|
return (0); // .eq. |
433 |
|
|
} |
434 |
|
|
|
435 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
436 |
|
|
|
437 |
|
|
int bfOpen (FILE **f, BaseCtrl *bc, char *ext, char *opt) |
438 |
|
|
{ char st [81]; |
439 |
|
|
if (strlen (bc->name) + strlen (ext) > 80) return (-2); |
440 |
|
|
strcpy (st, bc->name); strcat (st, ext); |
441 |
|
|
if ((*f = fopen (st, opt)) == NULL) return (-1); |
442 |
|
|
return (0); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
446 |
|
|
|
447 |
|
|
int InitBase (BaseCtrl *bc) |
448 |
|
|
// Error return: -1 base file/s; -2 inv. file/s; -3 mst. ctrl rec/s; |
449 |
|
|
// -4 cnt param/s; -5 ifp param/s |
450 |
|
|
{ ifpBlock ib; |
451 |
|
|
bc->opened = 0; |
452 |
|
|
if (bfOpen (&bc->mst, bc, ".MST", "rb") != 0) return (-1); |
453 |
|
|
bc->opened += 1; // MST opened |
454 |
|
|
if (bfOpen (&bc->xrf, bc, ".XRF", "rb") != 0) return (-1); |
455 |
|
|
bc->opened += 2; // XRF opened |
456 |
|
|
if (bfOpen (&bc->ifp, bc, ".CNT", "rb") != 0) return (-2); |
457 |
|
|
if (fread (&bc->cnt1, sizeof (cntBlock), 1, bc->ifp) == 0 || |
458 |
|
|
fread (&bc->cnt2, sizeof (cntBlock), 1, bc->ifp) == 0) return (-2); |
459 |
|
|
if (fclose (bc->ifp) != 0) return (-3); |
460 |
|
|
if (bfOpen (&bc->ifp, bc, ".IFP", "rb") != 0) return (-2); |
461 |
|
|
bc->opened += 4; // IFP opened |
462 |
|
|
if (bfOpen (&bc->n01, bc, ".N01", "rb") != 0) return (-2); |
463 |
|
|
bc->opened += 8; // N01 opened |
464 |
|
|
if (bfOpen (&bc->l01, bc, ".L01", "rb") != 0) return (-2); |
465 |
|
|
bc->opened += 16; // L01 opened |
466 |
|
|
if (bfOpen (&bc->n02, bc, ".N02", "rb") != 0) return (-2); |
467 |
|
|
bc->opened += 32; // N02 opened |
468 |
|
|
if (bfOpen (&bc->l02, bc, ".L02", "rb") != 0) return (-2); |
469 |
|
|
bc->opened += 64; // L02 opened |
470 |
|
|
if (fread (&bc->mctrl, sizeof (mstControl), 1, bc->mst) == 0) return (-3); |
471 |
|
|
if (bc->cnt1.ordn != 5 || bc->cnt1.ordf != 5 || bc->cnt1.n != 15 || |
472 |
|
|
bc->cnt1.k != 5 || bc->cnt2.ordn != 5 || bc->cnt2.ordf != 5 || |
473 |
|
|
bc->cnt2.n != 15 || bc->cnt2.k != 5) return (-4); |
474 |
|
|
if (fread (&ib, sizeof (ifpBlock), 1, bc->ifp) == 0) return (-5); |
475 |
|
|
if (ib.ifblk != 1) return (-5); |
476 |
|
|
bc->ibm = ib.ifrec [0]; bc->ipm = ib.ifrec [1]; |
477 |
|
|
return (0); |
478 |
|
|
} |
479 |
|
|
|
480 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
481 |
|
|
|
482 |
|
|
void Done (BaseCtrl *bc) // Close the database files |
483 |
|
|
{ |
484 |
|
|
if (bc->opened && 1) fclose (bc->mst); |
485 |
|
|
if (bc->opened && 2) fclose (bc->xrf); |
486 |
|
|
if (bc->opened && 4) fclose (bc->ifp); |
487 |
|
|
if (bc->opened && 8) fclose (bc->n01); |
488 |
|
|
if (bc->opened && 16) fclose (bc->l01); |
489 |
|
|
if (bc->opened && 32) fclose (bc->n02); |
490 |
|
|
if (bc->opened && 64) fclose (bc->l02); |
491 |
|
|
} |
492 |
|
|
|
493 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
494 |
|
|
|
495 |
|
|
char UpMe (char c) // ^A = ^a etc. |
496 |
|
|
{ |
497 |
|
|
if (c > 96) c = c - 32; |
498 |
|
|
return (c); |
499 |
|
|
} |
500 |
|
|
|
501 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
502 |
|
|
|
503 |
|
|
void outS (char *st) |
504 |
|
|
{ char i; |
505 |
|
|
if (st == NULL) return; |
506 |
|
|
for (i = 0; i < strlen (st); i++) |
507 |
|
|
// c = tblconvert [st [i]]; |
508 |
|
|
if (st [i] == (char) 145) printf ("<"); // This is HTML < |
509 |
|
|
else if (st [i] == (char) 146) printf (">"); // and that is > |
510 |
|
|
else printf ("%c", st [i]); |
511 |
|
|
} |
512 |
|
|
|
513 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
514 |
|
|
|
515 |
|
|
void outC (char ch) |
516 |
|
|
{ char st [2]; |
517 |
|
|
st [0] = ch; st [1] = 0; outS (st); |
518 |
|
|
} |
519 |
|
|
|
520 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
521 |
|
|
|
522 |
|
|
void outD (double x, int n) |
523 |
|
|
{ char s [80]; |
524 |
|
|
gcvt (x, n, s); |
525 |
|
|
outS (s); |
526 |
|
|
} |
527 |
|
|
|
528 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
529 |
|
|
|
530 |
|
|
void outN (long int x) // long int -> sting @ base=10 |
531 |
|
|
{ |
532 |
|
|
// char st [33]; |
533 |
|
|
// ltoa (x, st, 10); outS (st); |
534 |
|
|
printf ("%li", x); |
535 |
|
|
} |
536 |
|
|
|
537 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
538 |
|
|
|
539 |
|
|
|
540 |
|
|
// #include "imasterf.c" |
541 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
542 |
|
|
iAPI software: The Master File access to Unix-ISIS databases |
543 |
|
|
Copyright (C) 2000 by Robert Janusz |
544 |
|
|
E-mail: rj@jezuici.krakow.pl |
545 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
546 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
547 |
|
|
|
548 |
|
|
This program is free software; you can redistribute it and/or |
549 |
|
|
modify it under the terms of the GNU General Public License |
550 |
|
|
as published by the Free Software Foundation. |
551 |
|
|
|
552 |
|
|
This program is distributed in the hope that it will be useful, |
553 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
554 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
555 |
|
|
GNU General Public License for more details. |
556 |
|
|
|
557 |
|
|
You should have received a copy of the GNU General Public License |
558 |
|
|
along with this program; if not, write to the Free Software |
559 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
560 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
561 |
|
|
|
562 |
|
|
// gcc Linux Compiler conventions ! |
563 |
|
|
// *** ONLY UNIX ISIS = the difference between DOS/UNIX structures |
564 |
|
|
|
565 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
566 |
|
|
|
567 |
|
|
int GetRec (BaseCtrl *bc, long int mfnr, RecCtrl *rc, int bufvol) |
568 |
|
|
{ char mblk [512]; // Master File block; |
569 |
|
|
long int xmfb, xmfp; // Pointer to Master File (last read) record |
570 |
|
|
// xMfB < 0 : record deleted (status = 1), -xMfB --> block; |
571 |
|
|
// xMfP = 0: deleted phisicaly |
572 |
|
|
// = 0 & = 0: does not exist |
573 |
|
|
// 1st block: xMfB = 1, xMfP = 0; pointer = xMfB * 2048 + xMfP |
574 |
|
|
// ==> mst < 500 MBy; |
575 |
|
|
long int xn, xb; |
576 |
|
|
int ret, nch; |
577 |
|
|
xrfBlock xblk; |
578 |
|
|
mstHdrFix *hf = &rc->hdrs.mhf; |
579 |
|
|
mstHdrTxt *ht = &rc->hdrs.mht; |
580 |
|
|
char *b = rc->buf; |
581 |
|
|
|
582 |
|
|
if ((mfnr < 1) || (mfnr >= bc->mctrl.nxtmfn)) return (-2); // No record |
583 |
|
|
|
584 |
|
|
// Find the address in XRF... |
585 |
|
|
xn = mfnr - 1; xb = xn / 127; |
586 |
|
|
if (ReadMem (&xblk, bc->xrf, xb, sizeof (xrfBlock)) != 0) return (-1); |
587 |
|
|
xn = xblk.xrec [xn % 127]; // = address in MST |
588 |
|
|
xmfb = xn / 2048; // Master File Block |
589 |
|
|
xmfp = xn % 512; // Master File Position |
590 |
|
|
|
591 |
|
|
// Find the record in MST... |
592 |
|
|
if (xmfb < 1) return (1); // Record deleted |
593 |
|
|
ret = 0; // Record o.k. |
594 |
|
|
if (ReadMem (&mblk, bc->mst, xmfb - 1, sizeof (mblk)) != 0) return (-1); |
595 |
|
|
|
596 |
|
|
// Copy headers into record buffer... |
597 |
|
|
memcpy (b, &mblk [xmfp], sizeof (mstHdrFix)); |
598 |
|
|
if (hf->mfn != mfnr) return (-2); // Database corrupted |
599 |
|
|
if (hf->mfrl >= bufvol) return (-3); // Buffer too small |
600 |
|
|
|
601 |
|
|
// Get the rest of the record |
602 |
|
|
xmfp += sizeof (mstHdrFix); // Posinion in block |
603 |
|
|
xb = sizeof (mstHdrFix); // Position in buf |
604 |
|
|
xn = labs (hf->mfrl) - xb; // Number of chars to read |
605 |
|
|
if (xn <= 0) return (4); // No fields ?? |
606 |
|
|
for ( ; ; ) // We have some chars |
607 |
|
|
{ // Find number of chars to copy from this block |
608 |
|
|
if (xn <= (nch = sizeof (mblk) - xmfp)) nch = xn; |
609 |
|
|
memcpy (b + xb, &mblk [xmfp], nch); |
610 |
|
|
xb += nch; xn -= nch; xmfp = 0; |
611 |
|
|
if (xn <= 0) break; // Nothing more to read |
612 |
|
|
if (fread (&mblk, sizeof (mblk), 1, bc->mst) == 0) return (-1); |
613 |
|
|
} |
614 |
|
|
|
615 |
|
|
if (ht->status != 0) ret = 1; // Record deleted logicaly |
616 |
|
|
if (hf->mfbwb != 0 || hf->mfbwp != 0) ret = 2; // Record not inv. |
617 |
|
|
if (hf->mfrl < 0) ret = 3; // Record blocked |
618 |
|
|
return (ret); |
619 |
|
|
} |
620 |
|
|
|
621 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
622 |
|
|
|
623 |
|
|
int IsF (RecCtrl *rc, short int v, char ch, char *st) |
624 |
|
|
{ short int n, k, kk, flag; |
625 |
|
|
char *b = rc->buf; |
626 |
|
|
mstHdrTxt *mht = &rc->hdrs.mht; |
627 |
|
|
mstIndex *ind = (mstIndex *) &rc->buf [sizeof (RecHeaders)]; |
628 |
|
|
|
629 |
|
|
flag = 0; |
630 |
|
|
for (n = 0; n < mht->nvf; n++) |
631 |
|
|
{ |
632 |
|
|
if (ind->tag == v) // there is a tag |
633 |
|
|
{ |
634 |
|
|
if (ch == ' ') // field found |
635 |
|
|
{ flag = 1; break; } |
636 |
|
|
else // there is sub-field |
637 |
|
|
{ flag = 1; |
638 |
|
|
kk = 0; k = mht->base + ind->pos; |
639 |
|
|
while (b [k] != '^' || b [k + 1] != ch) // convention ;-) |
640 |
|
|
{ k += 1; kk += 1; |
641 |
|
|
if (kk >= ind->len) // out of field |
642 |
|
|
return (0); |
643 |
|
|
} |
644 |
|
|
break; |
645 |
|
|
} |
646 |
|
|
} |
647 |
|
|
ind += 1; // next index ref. |
648 |
|
|
} |
649 |
|
|
if (flag == 0) return (0); // false |
650 |
|
|
if (st == NULL) return (1); // true |
651 |
|
|
else |
652 |
|
|
if (sComp (&b [mht->base + ind->pos], st, ind->len) == 0) |
653 |
|
|
return (1); |
654 |
|
|
else return (0); |
655 |
|
|
} |
656 |
|
|
|
657 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
658 |
|
|
|
659 |
|
|
void RepF (RecCtrl *rc, char nf, ...) |
660 |
|
|
|
661 |
|
|
// Repeated "nf" fields in record "rc", the left label appears only if: |
662 |
|
|
// - begins with "\n", - there was another field and there is defined |
663 |
|
|
// filed; the right label appears only if ther was defined field. |
664 |
|
|
|
665 |
|
|
{ va_list pinfo; // for ... parameter list |
666 |
|
|
int i, c, flag, n, k, kk, v; |
667 |
|
|
int hit = 0; |
668 |
|
|
char *sl, *sr; |
669 |
|
|
char *b = rc->buf; |
670 |
|
|
mstHdrTxt *mht = &rc->hdrs.mht; |
671 |
|
|
mstIndex *ind = (mstIndex *) &rc->buf [sizeof (RecHeaders)]; |
672 |
|
|
|
673 |
|
|
for (n = 0; n < mht->nvf; n++) |
674 |
|
|
{ |
675 |
|
|
va_start (pinfo, nf); |
676 |
|
|
for (i = 0; i < nf; i++) |
677 |
|
|
{ |
678 |
|
|
kk = 0; |
679 |
|
|
k = mht->base + ind->pos; |
680 |
|
|
sl = va_arg (pinfo, char *); // left |
681 |
|
|
v = va_arg (pinfo, short int); // field |
682 |
|
|
c = va_arg (pinfo, char); // sub-field |
683 |
|
|
c = UpMe (c); |
684 |
|
|
sr = va_arg (pinfo, char *); // right |
685 |
|
|
if (v != ind->tag) // another Tag |
686 |
|
|
break; |
687 |
|
|
if (c != ' ') // sub-field |
688 |
|
|
{ flag = 1; |
689 |
|
|
while (b [k] != '^' || UpMe (b [k + 1]) != c) // convention ;-) |
690 |
|
|
{ k += 1; kk += 1; |
691 |
|
|
if (kk >= ind->len) |
692 |
|
|
{ flag = 0; break; } |
693 |
|
|
} |
694 |
|
|
if (flag) { k += 2; kk += 2; } |
695 |
|
|
} |
696 |
|
|
else flag = 1; |
697 |
|
|
if (flag) |
698 |
|
|
{ // Reference to NULL = NW error !!! |
699 |
|
|
if (sl == NULL) flag = 0; |
700 |
|
|
else if (*sl == '\n') flag = 1; else flag = 0; |
701 |
|
|
if (hit != 0 || flag) outS (sl); |
702 |
|
|
hit += 1; |
703 |
|
|
if (c == ' ') |
704 |
|
|
while (kk < ind->len) |
705 |
|
|
{ |
706 |
|
|
if (b [k] != '<' && b [k] != '>') // HTML special ;-) |
707 |
|
|
outC (b [k]); |
708 |
|
|
k += 1; kk += 1; |
709 |
|
|
} |
710 |
|
|
else |
711 |
|
|
while (kk < ind->len && b [k] != '^') // convention ;-) |
712 |
|
|
{ |
713 |
|
|
if (b [k] != '<' && b [k] != '>') // HTML special ;-) |
714 |
|
|
outC (b [k]); |
715 |
|
|
k += 1; kk += 1; |
716 |
|
|
} |
717 |
|
|
outS (sr); |
718 |
|
|
} |
719 |
|
|
} |
720 |
|
|
va_end (pinfo); |
721 |
|
|
ind += 1; |
722 |
|
|
} |
723 |
|
|
} |
724 |
|
|
|
725 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
726 |
|
|
|
727 |
|
|
// #include "iinvterm.c" |
728 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
729 |
|
|
iAPI software: The Inv. File Terms access for Unix-ISIS databases |
730 |
|
|
Copyright (C) 2000 by Robert Janusz |
731 |
|
|
E-mail: rj@jezuici.krakow.pl |
732 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
733 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
734 |
|
|
|
735 |
|
|
This program is free software; you can redistribute it and/or |
736 |
|
|
modify it under the terms of the GNU General Public License |
737 |
|
|
as published by the Free Software Foundation. |
738 |
|
|
|
739 |
|
|
This program is distributed in the hope that it will be useful, |
740 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
741 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
742 |
|
|
GNU General Public License for more details. |
743 |
|
|
|
744 |
|
|
You should have received a copy of the GNU General Public License |
745 |
|
|
along with this program; if not, write to the Free Software |
746 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
747 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
748 |
|
|
|
749 |
|
|
// gcc Linux Compiler conventions ! |
750 |
|
|
// *** ONLY UNIX ISIS = the difference between DOS/UNIX structures |
751 |
|
|
|
752 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
753 |
|
|
|
754 |
|
|
int FindFirst (TableQuery *tq) |
755 |
|
|
{ |
756 |
|
|
short int i, j // Indexes for idx [] |
757 |
|
|
, srec, klen, sidx; // Size (rec), key length, size (idx) |
758 |
|
|
long int r; // Reference (record number); < 0: --> L0x --> IFP |
759 |
|
|
char *ref; |
760 |
|
|
leafHeader *lhdr = &tq->lbl.lb1.hdr; // = ...lb2.hdr |
761 |
|
|
nodeBlock nbl; |
762 |
|
|
nodeHeader *nhdr = &nbl.nb1.hdr; // = ...nb2.hdr |
763 |
|
|
|
764 |
|
|
if (tq->it == 1) |
765 |
|
|
{ klen = 10; srec = sizeof (nodeBlock1); sidx = sizeof (nodeIndex1); } |
766 |
|
|
else |
767 |
|
|
{ klen = 30; srec = sizeof (nodeBlock2); sidx = sizeof (nodeIndex2); } |
768 |
|
|
|
769 |
|
|
r = tq->cntr->posrx; // Root in N0x |
770 |
|
|
while (r > 0L) |
771 |
|
|
{ |
772 |
|
|
if (ReadMem (&nbl, tq->n0x, r - 1, srec) != 0) return (-1); |
773 |
|
|
j = nhdr->ock; |
774 |
|
|
if (nhdr->pos != r || nhdr->it != tq->it || |
775 |
|
|
j < 1 || j > 10) return (-3); // 10 = 2*ordn |
776 |
|
|
ref = (char *) &nbl.nb1.idx; // Reference to first elem. of index |
777 |
|
|
ref += sidx; // The first key is allways <= st, skip it |
778 |
|
|
for (i = 1; i < j; i++) |
779 |
|
|
if (sComp (ref, tq->st, klen) > 0) break; |
780 |
|
|
else ref += sidx; |
781 |
|
|
ref -= sidx; // Correct value |
782 |
|
|
r = *(long int *) (ref + klen); // We have the "ref" value |
783 |
|
|
if (r > tq->cntr->nmaxpos) return (-3); // Out of N0x |
784 |
|
|
} |
785 |
|
|
|
786 |
|
|
// Now find the term in L0x index |
787 |
|
|
if (tq->it == 1) |
788 |
|
|
{ srec = sizeof (leafBlock1); sidx = sizeof(leafKey1); } |
789 |
|
|
else |
790 |
|
|
{ srec = sizeof(leafBlock2); sidx = sizeof(leafKey2); } |
791 |
|
|
|
792 |
|
|
r = - r; |
793 |
|
|
if (ReadMem (&tq->lbl, tq->l0x, r - 1, srec) != 0) return (-1); |
794 |
|
|
j = lhdr->ock; |
795 |
|
|
if (lhdr->pos != r || lhdr->it != tq->it || |
796 |
|
|
j < 1 || j > 10) return (-2); // 10 = 2*ordf |
797 |
|
|
|
798 |
|
|
tq->ilk = 0; |
799 |
|
|
ref = (char *) &tq->lbl.lb1.idx; // Reference to first elem. of index |
800 |
|
|
ref += sidx; // The first key is allways <= s, skip it |
801 |
|
|
for (i = 1; i < j; i++) |
802 |
|
|
if (sComp (ref, tq->st, klen) > 0) break; |
803 |
|
|
else { ref += sidx; tq->ilk += 1; } |
804 |
|
|
|
805 |
|
|
ref -= sidx; |
806 |
|
|
tq->term = ref; // We have the term address |
807 |
|
|
if (tq->it == 1) |
808 |
|
|
ref += 12; // += 10; *** NOT UNIX |
809 |
|
|
else ref += 32; // += 30; *** NOT UNIX |
810 |
|
|
tq->ib = *(long int *) ref; // = infb |
811 |
|
|
ref += sizeof (long int); |
812 |
|
|
tq->ip = *(long int *) ref; // = infp |
813 |
|
|
return (0); // O.K. |
814 |
|
|
} |
815 |
|
|
|
816 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
817 |
|
|
|
818 |
|
|
int FindNext (TableQuery *tq) |
819 |
|
|
{ int srec; // Block size |
820 |
|
|
long int r; // Reference (record number); < 0: --> L0x --> IFP |
821 |
|
|
leafHeader *lhdr = &tq->lbl.lb1.hdr; // = ...lb2.hdr |
822 |
|
|
|
823 |
|
|
if (tq->it == 1) srec = sizeof (leafBlock1); |
824 |
|
|
else srec = sizeof (leafBlock2); |
825 |
|
|
|
826 |
|
|
tq->ilk += 1; // Next key in the index |
827 |
|
|
if (tq->ilk >= lhdr->ock) // Out of index |
828 |
|
|
{ r = lhdr->ps; // Next L0x record in order |
829 |
|
|
if (r <= 0) |
830 |
|
|
{ tq->ilk -= 1; return (1); } // Nothing more, end of index |
831 |
|
|
if (ReadMem (&tq->lbl, tq->l0x, r - 1, srec) != 0) return (-1); |
832 |
|
|
if (lhdr->pos != r || lhdr->it != tq->it || |
833 |
|
|
lhdr->ock < 1 || lhdr->ock > 10) return (-2); // 10 = 2*ordf |
834 |
|
|
tq->ilk = 0; |
835 |
|
|
} |
836 |
|
|
|
837 |
|
|
srec = tq->ilk; |
838 |
|
|
if (tq->it == 1) |
839 |
|
|
{ tq->term = tq->lbl.lb1.idx [srec].key; |
840 |
|
|
tq->ib = tq->lbl.lb1.idx [srec].infb; |
841 |
|
|
tq->ip = tq->lbl.lb1.idx [srec].infp; |
842 |
|
|
} |
843 |
|
|
else |
844 |
|
|
{ tq->term = tq->lbl.lb2.idx [srec].key; |
845 |
|
|
tq->ib = tq->lbl.lb2.idx [srec].infb; |
846 |
|
|
tq->ip = tq->lbl.lb2.idx [srec].infp; |
847 |
|
|
} |
848 |
|
|
return (0); // We have the new key |
849 |
|
|
} |
850 |
|
|
|
851 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
852 |
|
|
|
853 |
|
|
int Find (BaseCtrl *bc, TableQuery tabq [], int ifind, long int *npg |
854 |
|
|
, RecCtrl *rc, long int recvol) |
855 |
|
|
{ int i; |
856 |
|
|
|
857 |
|
|
if (ifind <= 0 || ifind > NFIND) return (-1); |
858 |
|
|
for (i = 0; i < ifind; i++) |
859 |
|
|
if (FindFirst (&tabq [i]) < 0) return (-1); |
860 |
|
|
|
861 |
|
|
i = Postings (bc, tabq, ifind, npg, rc, recvol); |
862 |
|
|
return (i); |
863 |
|
|
} |
864 |
|
|
|
865 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
866 |
|
|
|
867 |
|
|
int IndexPrep (BaseCtrl *bc, TableQuery *tq1, TableQuery *tq2, char *st) |
868 |
|
|
{ char sx [31]; // tqx->v contains the status of L0x index |
869 |
|
|
int i; |
870 |
|
|
|
871 |
|
|
if (st == NULL) |
872 |
|
|
for (i = 0; i < 30; i++) sx [i] = ' '; |
873 |
|
|
else |
874 |
|
|
for (i = 0; i < 30; i++) |
875 |
|
|
if (i < strlen (st)) sx [i] = st [i]; else sx [i] = ' '; |
876 |
|
|
|
877 |
|
|
sx [30] = 0; |
878 |
|
|
setQuery (bc, tq2, sx, 0); // We have a long term in tq2; v := 0 |
879 |
|
|
if (FindFirst (tq2) < 0) return (-1); |
880 |
|
|
|
881 |
|
|
sx [10] = 0; |
882 |
|
|
setQuery (bc, tq1, sx, 0); // We have a short term in tq1; v := 0 |
883 |
|
|
if (FindFirst (tq1) < 0) return (-1); |
884 |
|
|
|
885 |
|
|
while (sComp (tq1->term, tq1->st, 10) < 0) |
886 |
|
|
if ((tq1->v = FindNext (tq1)) != 0) break; // At the end or error |
887 |
|
|
if (tq1->v < 0) return (-1); |
888 |
|
|
|
889 |
|
|
while (sComp (tq2->term, tq2->st, 30) < 0) |
890 |
|
|
if ((tq2->v = FindNext (tq2)) != 0) break; // At the end or error |
891 |
|
|
if (tq2->v < 0) return (-1); |
892 |
|
|
|
893 |
|
|
return (IndexTest (tq1, tq2)); |
894 |
|
|
} |
895 |
|
|
|
896 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
897 |
|
|
|
898 |
|
|
int IndexTest (TableQuery *tq1, TableQuery *tq2) |
899 |
|
|
{ |
900 |
|
|
if (tq1->v == 1) // At the end of 1st |
901 |
|
|
if (tq2->v == 1) // At the end of 2nd |
902 |
|
|
return (0); // All done |
903 |
|
|
else return (2); // We have only 2nd |
904 |
|
|
else |
905 |
|
|
if (tq2->v == 1) return (1); // We have only 1st |
906 |
|
|
else if (sComp (tq1->term, tq2->term, 10) <= 0) return (1); |
907 |
|
|
else return (2); |
908 |
|
|
} |
909 |
|
|
|
910 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
911 |
|
|
|
912 |
|
|
int IndexTerm (int i, TableQuery *tq1, TableQuery *tq2) |
913 |
|
|
{ |
914 |
|
|
if (i == 1) tq1->v = FindNext (tq1); // The term was in 1st |
915 |
|
|
else if (i == 2) tq2->v = FindNext (tq2); // The term was in 2nd |
916 |
|
|
else return (-1); |
917 |
|
|
return (IndexTest (tq1, tq2)); |
918 |
|
|
} |
919 |
|
|
|
920 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
921 |
|
|
|
922 |
|
|
void setQuery (BaseCtrl *bc, TableQuery *tq, char *sx, short int fld) |
923 |
|
|
{ // Must be activated AFTER the initialization of database |
924 |
|
|
|
925 |
|
|
tq->v = fld; |
926 |
|
|
if (strlen (sx) <= 10) |
927 |
|
|
{ tq->it = 1; doUpcase (tq->st, sx, 10); |
928 |
|
|
tq->cntr = &bc->cnt1; tq->n0x = bc->n01; tq->l0x = bc->l01; |
929 |
|
|
} |
930 |
|
|
else |
931 |
|
|
{ tq->it = 2; doUpcase (tq->st, sx, 30); |
932 |
|
|
tq->cntr = &bc->cnt2; tq->n0x = bc->n02; tq->l0x = bc->l02; |
933 |
|
|
} |
934 |
|
|
} |
935 |
|
|
|
936 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
937 |
|
|
|
938 |
|
|
|
939 |
|
|
// #include "ipost.c" |
940 |
|
|
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
941 |
|
|
iAPI software: The Inv. File Postings access for Unix-ISIS databases |
942 |
|
|
Copyright (C) 2000 by Robert Janusz |
943 |
|
|
E-mail: rj@jezuici.krakow.pl |
944 |
|
|
Address: Robert Janusz, ul. Kopernika 26, 31-501 Krakow, Poland |
945 |
|
|
tel: (0048-12) 4294416/432 ; fax: (0048-12) 4295003. |
946 |
|
|
|
947 |
|
|
This program is free software; you can redistribute it and/or |
948 |
|
|
modify it under the terms of the GNU General Public License |
949 |
|
|
as published by the Free Software Foundation. |
950 |
|
|
|
951 |
|
|
This program is distributed in the hope that it will be useful, |
952 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
953 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
954 |
|
|
GNU General Public License for more details. |
955 |
|
|
|
956 |
|
|
You should have received a copy of the GNU General Public License |
957 |
|
|
along with this program; if not, write to the Free Software |
958 |
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
959 |
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ |
960 |
|
|
|
961 |
|
|
// gcc Linux Compiler conventions ! |
962 |
|
|
// *** ONLY UNIX ISIS = the difference between DOS/UNIX structures |
963 |
|
|
|
964 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
965 |
|
|
|
966 |
|
|
int PostSeg (BaseCtrl *bc, TableQuery *tq) |
967 |
|
|
{ |
968 |
|
|
if (ReadMem (&tq->ibl, bc->ifp, tq->ib - 1, sizeof (ifpBlock)) != 0) |
969 |
|
|
return (-1); |
970 |
|
|
if (labs (tq->ibl.ifblk) - tq->ib != 0) return (-2); |
971 |
|
|
memcpy (&tq->ihd, &tq->ibl.ifrec [tq->ip], sizeof (ifpHeader)); |
972 |
|
|
tq->ip += 3; // = long int.s / (header - posting) ***!= ISIS.MANUAL *** |
973 |
|
|
tq->iiseg = 0; |
974 |
|
|
return (0); |
975 |
|
|
} |
976 |
|
|
|
977 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
978 |
|
|
|
979 |
|
|
int PostNext (BaseCtrl *bc, TableQuery *tq) |
980 |
|
|
{ |
981 |
|
|
if (tq->iitot >= tq->iall) return (1); // No more postings |
982 |
|
|
if (tq->iiseg >= tq->ihd.ifpsegp) // No more postings in this seg. |
983 |
|
|
{ // Get next Segment... |
984 |
|
|
tq->ib = tq->ihd.ifpnxtb; tq->ip = tq->ihd.ifpnxtp; |
985 |
|
|
if (PostSeg (bc, tq) != 0) return (-2); |
986 |
|
|
} |
987 |
|
|
tq->iiseg += 1; tq->iitot += 1; |
988 |
|
|
tq->ip += 2; // = Number of long int / posting ***!= ISIS.MANUAL *** |
989 |
|
|
if (tq->ip > 125) // ***!= ISIS.MANUAL *** |
990 |
|
|
{ // Get next block for this segment; we HAVE TO find the right block! |
991 |
|
|
tq->ib += 1; tq->ip = 0; |
992 |
|
|
if (ReadMem (&tq->ibl, bc->ifp, tq->ib - 1, sizeof (ifpBlock)) != 0) |
993 |
|
|
return (-1); |
994 |
|
|
if (labs (tq->ibl.ifblk) != tq->ib) return (-3); |
995 |
|
|
} |
996 |
|
|
tq->ipst = (char *) &tq->ibl.ifrec [tq->ip]; |
997 |
|
|
return (0); |
998 |
|
|
} |
999 |
|
|
|
1000 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1001 |
|
|
|
1002 |
|
|
void PostMake (long int mfn, short int tag, char occ, short int pcnt |
1003 |
|
|
, char *s, char *slen) |
1004 |
|
|
{ ifpPosting rnp; |
1005 |
|
|
char *p = (char *) &rnp; |
1006 |
|
|
|
1007 |
|
|
rnp.pmfn = mfn; rnp.ptag = tag; rnp.pocc = occ; rnp.pcnt = pcnt; |
1008 |
|
|
if (tag == 0) *slen = 3; // Only MFN |
1009 |
|
|
else *slen = 5; // MFN and TAG |
1010 |
|
|
s [2] = p [0]; s [1] = p [1]; s [0] = p [2]; // = pmfn |
1011 |
|
|
s [4] = p [4]; s [3] = p [5]; s [5] = p [6]; s [7] = p [7]; s [6] = p [8]; |
1012 |
|
|
} |
1013 |
|
|
|
1014 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1015 |
|
|
|
1016 |
|
|
void PostInv (ifpPosting *ifpp, void *ps) |
1017 |
|
|
{ char *p = (char *) ifpp; |
1018 |
|
|
char *s = (char *) ps; |
1019 |
|
|
|
1020 |
|
|
// Posting string: |0 a |1 b |2 c |3 d |4 e |5 f |6 g |7 h | ps *s |
1021 |
|
|
// ifpPosting: |0 c|1 b |2 a |3 0 |4 e |5 d |6 f |7 h |8 g | ifpp *p |
1022 |
|
|
// |pmfn |ptag |pocc|pcnt | |
1023 |
|
|
|
1024 |
|
|
p [0] = s [2]; p [1] = s [1]; p [2] = s [0]; p [3] = 0; // = pmfn |
1025 |
|
|
p [4] = s [4]; p [5] = s [3]; p [6] = s [5]; p [7] = s [7]; p [8] = s [6]; |
1026 |
|
|
} |
1027 |
|
|
|
1028 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1029 |
|
|
|
1030 |
|
|
|
1031 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1032 |
|
|
|
1033 |
|
|
int main (int argc, char **argv) // char *argv [] |
1034 |
|
|
{ char c; |
1035 |
|
|
|
1036 |
|
|
printf ("ix <database>\n"); |
1037 |
|
|
printf ("<database> ::= UNIX-ISIS (v.3) MF without .MST\n"); |
1038 |
|
|
printf ("ix ver. 0.3, Copyright (C) 2000 by Robert Janusz\n"); |
1039 |
|
|
printf ("ix comes with ABSOLUTELY NO WARRANTY\n"); |
1040 |
|
|
printf ("License: GPL; see http://www.gnu.org/ for details\n"); |
1041 |
|
|
|
1042 |
|
|
for (c = 'A'; c <= 'z'; c++) // Let's prepare it, we use API, not an example |
1043 |
|
|
UpCase [c] = UpMe (c); |
1044 |
|
|
|
1045 |
|
|
if (argv [1] != NULL) { |
1046 |
|
|
strcpy (DBpath, argv [1]); // Database; no test ! ;-) it's only an example |
1047 |
|
|
isis (); |
1048 |
|
|
} |
1049 |
|
|
|
1050 |
|
|
return (0); |
1051 |
|
|
} |
1052 |
|
|
|
1053 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1054 |
|
|
|
1055 |
|
|
void isis () |
1056 |
|
|
{ |
1057 |
|
|
int j, v, k; |
1058 |
|
|
long int nrc; |
1059 |
|
|
BaseCtrl bc; |
1060 |
|
|
RecCtrl rc; |
1061 |
|
|
char st [31]; |
1062 |
|
|
TableQuery tabq [NFIND]; |
1063 |
|
|
|
1064 |
|
|
strcpy (bc.name, DBpath); |
1065 |
|
|
InitBase (&bc); |
1066 |
|
|
|
1067 |
|
|
// ShowRec but not all... |
1068 |
|
|
|
1069 |
|
|
printf ("\n*** ShowRec ***\n\n"); |
1070 |
|
|
|
1071 |
|
|
//for (nrc = 1L; nrc < bc.mctrl.nxtmfn; nrc++) { |
1072 |
|
|
for (nrc = 10L; nrc < 20L; nrc++) { |
1073 |
|
|
if ((j = GetRec (&bc, nrc, &rc, RECLENGTH)) == 0) { |
1074 |
|
|
ShowRec (&rc); |
1075 |
|
|
} |
1076 |
|
|
} |
1077 |
|
|
|
1078 |
|
|
// ShowIndex |
1079 |
|
|
|
1080 |
|
|
printf ("\n*** ShowIndex: %s ***\n\n", st); |
1081 |
|
|
|
1082 |
|
|
strcpy (st, "TEST"); // just an Inv. File term |
1083 |
|
|
|
1084 |
|
|
v = 0; // term counter |
1085 |
|
|
k = IndexPrep (&bc, &tabq [0], &tabq [1], st); // prepare indexes |
1086 |
|
|
while (k > 0) { |
1087 |
|
|
j = 20 * k - 10; // We have the term length ;-) |
1088 |
|
|
memcpy (&st, &tabq [k - 1].term [0], j); // keep it in st |
1089 |
|
|
st [j] = 0; |
1090 |
|
|
if ((v += 1) > 12) // we want 12 terms in a list |
1091 |
|
|
{ |
1092 |
|
|
printf ("->%s\n", st); // the next term |
1093 |
|
|
break; |
1094 |
|
|
} |
1095 |
|
|
printf ("%s\n", st); |
1096 |
|
|
k = IndexTerm (k, &tabq [0], &tabq [1]); // Next term |
1097 |
|
|
} |
1098 |
|
|
|
1099 |
|
|
// Find a term & show records |
1100 |
|
|
|
1101 |
|
|
printf ("\n*** Search for: %s ***\n\n", st); // Let's use the last term |
1102 |
|
|
|
1103 |
|
|
setQuery (&bc, &tabq [0], st, 0); // String to search in a filed 0 = any |
1104 |
|
|
|
1105 |
|
|
j = Find (&bc, tabq, 1, &nrc, &rc, RECLENGTH); // 1 term to search for |
1106 |
|
|
|
1107 |
|
|
// Clean all |
1108 |
|
|
|
1109 |
|
|
printf ("\nO.K.\n"); |
1110 |
|
|
|
1111 |
|
|
Done (&bc); |
1112 |
|
|
} |
1113 |
|
|
|
1114 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1115 |
|
|
|
1116 |
|
|
void ShowRec (RecCtrl *rc) |
1117 |
|
|
{ long int nr; |
1118 |
|
|
short int n, k, kk; |
1119 |
|
|
char st [256]; |
1120 |
|
|
char *b = rc->buf; |
1121 |
|
|
mstHdrTxt *mht = &rc->hdrs.mht; |
1122 |
|
|
mstIndex *ind = (mstIndex *) &rc->buf [sizeof (RecHeaders)]; |
1123 |
|
|
|
1124 |
|
|
nr = rc->hdrs.mhf.mfn; // Record header |
1125 |
|
|
|
1126 |
|
|
printf ("=== %li\n", nr); |
1127 |
|
|
for (n = 0; n < mht->nvf; n++) |
1128 |
|
|
{ // Show fileds without formating |
1129 |
|
|
printf ("*** [%li] ", (long int) ind->tag); |
1130 |
|
|
k = mht->base + ind->pos; |
1131 |
|
|
for (kk = 0; kk < ind->len; kk++) |
1132 |
|
|
printf ("%c", b [k++]); |
1133 |
|
|
printf ("\n"); |
1134 |
|
|
ind += 1; // Next index |
1135 |
|
|
} |
1136 |
|
|
printf ("___\n"); |
1137 |
|
|
} |
1138 |
|
|
|
1139 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1140 |
|
|
|
1141 |
|
|
// This procedure is prepared to do a simple AND operator after some |
1142 |
|
|
// extensions, so it can be localy a little strange ;-) |
1143 |
|
|
|
1144 |
|
|
int Postings (BaseCtrl *bc, TableQuery tabq [], int ifind, long int *npg |
1145 |
|
|
, RecCtrl *rc, long int recvol) |
1146 |
|
|
{ int j, state; |
1147 |
|
|
long int ipg, rn; |
1148 |
|
|
ifpPosting ip; |
1149 |
|
|
TableQuery *tq; |
1150 |
|
|
|
1151 |
|
|
if (ifind < 1) goto finish; // nothing to do |
1152 |
|
|
|
1153 |
|
|
ipg = 1L; // Index for page break |
1154 |
|
|
|
1155 |
|
|
{ tq = &tabq [0]; // Let's think only about one term to handle (example) |
1156 |
|
|
if (PostSeg (bc, tq) != 0) return (-1); |
1157 |
|
|
tq->iall = tq->ihd.ifptotp; // Only 1st Segment has tot. post. number |
1158 |
|
|
tq->iitot = 0; |
1159 |
|
|
if (PostNext (bc, tq) != 0) return (-1); |
1160 |
|
|
PostInv (&ip, tq->ipst); |
1161 |
|
|
if (sComp (tq->st, tq->term, 20 * tq->it - 10) != 0) |
1162 |
|
|
ipg = 0L; // the term not found |
1163 |
|
|
} |
1164 |
|
|
|
1165 |
|
|
if (ipg != 1L) goto finish; |
1166 |
|
|
|
1167 |
|
|
for ( ; ; ) // Global loop... |
1168 |
|
|
{ |
1169 |
|
|
|
1170 |
|
|
// Is there a field |
1171 |
|
|
{ tq = &tabq [0]; |
1172 |
|
|
if (tq->v != 0) |
1173 |
|
|
while (ip.ptag != tq->v) |
1174 |
|
|
{ |
1175 |
|
|
if (PostNext (bc, tq) > 0) goto finish; // No more postings |
1176 |
|
|
PostInv (&ip, tq->ipst); |
1177 |
|
|
} |
1178 |
|
|
} |
1179 |
|
|
|
1180 |
|
|
rn = ip.pmfn; |
1181 |
|
|
|
1182 |
|
|
state = 1; |
1183 |
|
|
if (ip.pmfn != rn) |
1184 |
|
|
state = 0; |
1185 |
|
|
|
1186 |
|
|
if (state) // We have a record to show |
1187 |
|
|
{ |
1188 |
|
|
if ((j = GetRec (bc, rn, rc, recvol)) == 0) |
1189 |
|
|
ShowRec (rc); |
1190 |
|
|
else |
1191 |
|
|
printf ("Record state = %li\n", j); |
1192 |
|
|
|
1193 |
|
|
do // Shift all postings |
1194 |
|
|
{ tq = &tabq [0]; |
1195 |
|
|
if (PostNext (bc, tq) > 0) goto finish; // No more postings |
1196 |
|
|
PostInv (&ip, tq->ipst); |
1197 |
|
|
} |
1198 |
|
|
while (ip.pmfn <= rn); // MFN equals |
1199 |
|
|
} |
1200 |
|
|
else // state == 0, Shift all postings |
1201 |
|
|
while (ip.pmfn < rn) // The last is to examin |
1202 |
|
|
{ tq = &tabq [0]; |
1203 |
|
|
if (PostNext (bc, tq) > 0) goto finish; // No more postings |
1204 |
|
|
PostInv (&ip, tq->ipst); |
1205 |
|
|
} |
1206 |
|
|
} |
1207 |
|
|
|
1208 |
|
|
finish: |
1209 |
|
|
return (0); // The output is finished |
1210 |
|
|
} |
1211 |
|
|
|
1212 |
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1213 |
|
|
|