Line # Revision Author
1 237 dpavlin /*
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 xb