1
2
3                              Nodelist Version 7+
4
5                             Version 0, May 30 1997
6
7                    Alberto Pasquale, 2:332/504@fidonet.org
8                    Thomas Waldmann, 2:2474/400@fidonet.org
9
10
11                                     TOPIC
12
13        A new nodelist standard that remains FULLY compatible with V7
14        applications while adding new features and resolving the major
15        shortcomings of V7.
16
17
18        0. Why V7+ ?
19        ============
20
21        V7 is a commonly adopted standard for a "nodelist database"
22        (often V7 is also called a "nodelist index", but this is only
23        half of the truth - *.NDX is the index, but *.DAT is some sort
24        of database file).
25
26        V7 uses B-tree indices for sysop names and system addresses and
27        is really FAST.
28
29        Many software uses V7 and a totally different standard maybe
30        would not get adopted by programmers.
31
32        But V7 has a great drawback: it currently does not put all
33        information that is contained in the "raw" nodelist into the V7
34        database.
35
36        So if you use V7, you do NOT have all nodelist information that
37        you maybe WANT to use (e.g. it does not support U,Txy (FSC-0062)
38        and other new flags, some characters get "lost" due to the
39        "packing" algorithm used etc.).
40
41        This drawback will be solved with V7+ - any thing that is
42        present in a raw nodelist will also be present in the V7+
43        database - no information is lost.
44
45        V7+ also introduces a Phone Index (useful for CID lookup) and a
46        whole set of "links" that allow to move through the Fidonet
47        structure:
48
49        - Ring of "same sysop" entries
50        - Ring of "same phone" entries
51        - Pointer to "first downlink"
52        - List of "same downlink level"
53        - Full Region and Hub information
54
55        Besides V7+ introduces a semaphore method to avoid collisions
56        between applications and the compiler.
57
58
59        1. Naming Convention
60        ====================
61
62        The base name is user specified; from here on it will be
63        referred to as <NODEX>.
64
65        Files already used by V7, that are also used by V7+:
66
67        <NODEX>.DAT The V7 / V7+ data file.
68                    V7+ remains fully compatible with V7, but adds a new
69                    field (8 hex digit pointer to the DTP entry) at the
70                    end of the packed data.
71
72        <NODEX>.NDX Traditional B-tree address index.
73
74        <NODEX>.SDX Traditional B-tree sysop index (case insensitive).
75                    For V7 compatibility, both compilers and
76                    applications MUST be able to use SYSOP.NDX instead
77                    of the default <NODEX>.SDX.
78
79        V7+ specific files:
80
81        <NODEX>.DTP V7+ Data file, contains complete nodelist
82                    information and compiler-generated links.
83
84        <NODEX>.PDX B-tree Phone index (case insensitive), to be used
85                    just as <NODEX>.SDX.
86
87
88        The application that finds <NODEX>.DTP can assume that a V7+
89        nodelist is available. It is the user responsibility to delete
90        old files if downgrading.
91
92        A compiler in V7+ mode MUST generate all the above files by
93        default (no need to specify anything more than "Version7+" and
94        <NODEX>).
95
96
97
98        2. V7 Database File (<NODEX>.DAT)
99        =================================
100
101        2.1. Old structure and procedure
102        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
103
104        struct _vers7
105        {
106          short Zone;         // Zone number
107          short Net;          // Net number
108          short Node;         // Node number
109          short HubNode;      // If a point, this is point number
110          word CallCost;      // phone company's charge
111          word MsgFee;        // Amount charged to user for a message
112          word NodeFlags;     // set of flags
113          byte ModemType;     // Modem type
114          byte Phone_len;     // length of phone number (not packed)
115          byte Password_len;  // length of password (not packed)
116          byte Bname_len;     // length of system name (unpacked)
117          byte Sname_len;     // length of Sysop's name (unpacked)
118          byte Cname_len;     // length of City's name (unpacked)
119          byte pack_len;      // total length of packed data
120          byte BaudRate;      // baud rate divided by 300
121        };
122
123
124        Accessing V7 data is currently done like this:
125
126         1. find the stuff in the index - result is the "datpos" value -
127            the offset into the <NODEX>.DAT file
128
129         2. Seek to offset <datpos> into the <NODEX>.DAT file
130
131         3. Read sizeof(struct _vers7) bytes out of the <NODEX>.DAT file
132            into a variable of type  struct _vers7
133
134         4. Read the next <Phone_len> bytes out of the <NODEX>.DAT file
135            -> Phone Number
136
137         5. Read the next <Password_len> bytes out of the <NODEX>.DAT
138            file -> Password
139
140         6. Read the next <pack_len> bytes out of the <NODEX>.DAT file
141            -> some "packed" data
142
143         7. Unpack the "packed" data
144
145         8. First <Bname_len> bytes of the unpacked data contain the
146            System's (BBS') name
147
148         9. Next <Sname_len> bytes of the unpacked data contain the
149            Sysop's name
150
151        10. Next <Cname_len> bytes of the unpacked data contain the
152            City's name
153
154
155        Data layout in the <NODEX>.DAT file is like that:
156
157        <_vers7 struct>
158        <Not packed: Phone>
159        <Not packed: Password>
160        <Packed: <BBS name>
161                 <Sysop name>
162                 <City name>
163        >
164
165
166        2.2. New structure and procedure
167        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168
169        struct _vers7 is NOT changed: both indexed and sequential
170        accesses are guaranteed compatible with V7.
171
172        There's only a slight addition in the packed data, see below.
173
174        Accessing V7/V7+ data should be done like this:
175
176         1. |
177        ... |
178        10. | all the same as described in section 2.1 (compatibility!)
179
180        11. Check if there are 8 hex digits at the end of the packed
181            data, after <Bname_len>+<Sname_len>+<Cname_len> bytes (see
182            steps 7..10).
183
184            In a V7+ nodelist, you should _always_ find these 8 hex
185            digits at the end of the packed data, BUT a V7 nodelist
186            editor may have removed them from modified entries.
187
188            Applications MUST be able to handle the "missing 8 hex
189            digits" situation as a normal condition and proceed as
190            possible with the simple V7 data (some message signalling
191            the situation may be issued, abnormal termination is
192            unacceptable behaviour).
193
194            If the 8 hex digits are found, they represent an offset into
195            the new <NODEX>.DTP file.
196
197            Applications MUST ignore any data possibly following the 8
198            hex digit pointer.
199
200            Due to the V7 base-40 3:2 packing algorithm, the compilers
201            have to pad the data to be compressed so that its length is
202            a multiple of 3: it is recommended that the space (ASCII
203            0x20) is used.
204
205
206        12. Seek into <NODEX>.DTP to the offset you got in step 11.
207
208        13. Read/Process <NODEX>.DTP fields as described in section 3.
209
210
211        So the new data layout in the <NODEX>.DAT file is like that:
212
213        <_vers7 struct>
214        <Not packed: Phone>
215        <Not packed: Password>
216        <Packed: <BBS name>
217                 <Sysop name>
218                 <City name>
219                 <8-hex-digit-offset into <NODEX>.DTP>
220        >
221
222
223        3. <NODEX>.DTP file layout
224        ==========================
225
226        Let's define some glossary:
227
228        byte    8 bit unsigned integer
229        word   16 bit unsigned integer (LSB first)
230        dword  32 bit unsigned integer (LSB first)
231
232
233        The <NODEX>.DTP file has the following layout:
234
235        <Header>    File header
236        <Entry>     Entry for first compiled system
237        <Entry>     Entry for second compiled system
238        <Entry>     Entry for third compiled system
239        ...
240
241
242        3.1. <Header>
243        ~~~~~~~~~~~~~
244
245        <Header> has the following layout:
246
247        <Control>   Miscellaneous Information for Compatibility
248        <TopLink>   Link to top level fidonet hierarchy
249
250
251        3.1.1. <Control> Structure
252        ~~~~~~~~~~~~~~~~~~~~~~~~~~
253
254        struct _DTPCtl {
255            word size;          // Size of this control structure
256            byte Version;       // Version of DTP file
257            byte AllFixSize;    // sizeof (_DTPAllLnk)
258            byte AddFixSize;    // sizeof (_DTPNodeLnk)
259        };
260
261
262        size:
263              This structure may be expanded in the future, so size is
264              provided to allow compatible positioning on the following
265              <TopLink> record.
266
267        Version:
268              This is the V7+ Version, currently 0.
269              The compatibility towards previous versions is guaranteed,
270              so correctly behaved applications will have no problems
271              dealing with newer versions of V7+.
272
273              When new features will be added, new applications will be
274              able to check for the version level of the V7+ database,
275              while old ones will remain compatible.
276
277              The check will be "if Version >= n then ...".
278
279        AllFixSize:
280              This is the size of the fixed-length structure associated
281              with ANY system in the nodelist. It is provided to allow
282              compatible positioning on the following field, in the case
283              of future extensions.
284
285        AddFixSize:
286              This is the size of the fixed-length structure associated
287              with Nodes only (no points) and with <TopLink>. It is
288              provided to allow compatible positioning on the following
289              field, in the case of future extensions.
290
291
292        3.1.2. <TopLink>
293        ~~~~~~~~~~~~~~~~
294
295        V7+ has pointers to link the entire fidonet structure, from the
296        top coordinators to the points.
297
298        The <NODEX>.DTP header contains the link to the first (in
299        zone/region/net/hub/node/point order) "top level" system found
300        in the nodelist, usually ZC1.
301
302        struct _DTPNodeLnk {
303            word  ndowns;   // number of systems in lower level
304            dword FlOfs;    // DAT offset of "Lower Fido Level"
305        };
306
307
308        ndowns:
309              The number of direct downlinks; in this case it is the
310              number of "top level" systems (systems that do not have
311              uplinks in the nodelist).
312
313              Usually it's the number of ZCs.
314
315              Please note that if you have included a Region segment and
316              the corresponding Zone is not included in other nodelists
317              compiled to the same <NODEX>.*, this RC will be a "Top
318              Level" system. The same happens in the case of lower level
319              systems that are "orphans" of the upper coordinator.
320
321        FlOfs:
322              Offset into <NODEX>.DAT for the first direct downlink; in
323              this case it's usually ZC1.
324
325
326        3.2. <Entry>
327        ~~~~~~~~~~~~
328
329        This is the <NODEX>.DTP entry for each and every compiled
330        system, pointed to by the 8-hex-digit offset found at the end of
331        the _vers7 packed data.
332
333
334        The layout is:
335
336        <Links>                 Fixed size info (see <Header>)
337        <Raw-size>              word (size of following raw-line)
338        <Raw-nodelist-line>     variable size raw nodelist line
339
340
341        This layout may be expanded in the future, both in the
342        fixed-length and variable-length sections.
343
344        Please, always use the size information found in the <Header> to
345        remain compatible with future V7+ extensions.
346
347
348        3.2.1. <Links>
349        ~~~~~~~~~~~~~~
350
351        The layout is:
352
353         <AllLinks>     Common to all entries
354        [<NodeLink>]    Not present for Points
355
356
357        3.2.1.1. <AllLinks>
358        ~~~~~~~~~~~~~~~~~~~
359
360        The following structure is used for all the systems in the
361        nodelist.
362
363
364        struct _DTPAllLnk {
365            word  Region;  // Region
366            word  Hub;     // Hub
367            dword SOfs;    // DAT offset of next Same SysOp entry
368            dword POfs;    // DAT offset of next Same Phone entry
369            dword FeOfs;   // DAT offset of next "Equal Fido Level"
370            byte  Sn;      // Number (base 0) of SysOp entry (ADR order)
371            byte  Pn;      // Number (base 0) of Phone entry (ADR order)
372        };
373
374
375        Region:
376              Region number, 0 if none.
377
378        Hub:
379              Hub number, 0 if none.
380
381              Please note that the "NodeHub" field of _vers7 may not
382              always be the same as this one, not only because it is
383              absent for points, but also because the compiler may
384              infer the Hub from other nodelist entries while linking
385              <NODEX>.DTP.
386
387              DO NOT USE NodeHub in _vers7 for reliable Hub information.
388
389        SOfs:
390              Offset into <NODEX>.DAT for next system with the same
391              SysOp name (in order of Address).
392
393              0xffffffff if none.
394
395              This is a RING link, that is the last entry points to the
396              first one.
397
398        POfs:
399              Offset into <NODEX>.DAT for next system with the same
400              Phone number (in order of Address).
401
402              0xffffffff if none.
403
404              This is a RING link, that is the last entry points to the
405              first one.
406
407        FeOfs:
408              Offset into <NODEX>.DAT for next system at the same
409              "fidonet level", that is with the same direct
410              uplink/coordinator.
411
412              0xffffffff if none.
413
414              This is a LIST link, that is the last entry points nowhere
415              (0xffffffff).
416
417              Please note that "equal level" systems are not necessarily
418              all of the same coordination level (all HCs or RCs etc.).
419
420              For example a ZC may have as direct downlinks (linked with
421              FeOfs between one another):
422
423              - his points (usually administrative entries should not
424                have points, but it may happen),
425
426              - Independent nodes in the Zone
427
428              - Independent HCs in the Zone
429
430              - Independent NCs in the Zone
431
432              - RCs in the zone
433
434        Sn:
435              Number of same-sysop entry (0 based).
436              0xff if no link available.
437
438              Please do NOT use Sn to check for links, use SOfs instead.
439
440        Pn:
441              Number of same-phone entry (0 base).
442              0xff if no link available.
443
444              Please do NOT use Pn to check for links, use POfs instead.
445
446
447        When you are looking for a SysOp or Phone that has multiple
448        entries in the index, you get one and then you follow the links
449        (SOfs, POfs) through all the remaining entries.
450
451        Since the first entry (got from the index) may be in the middle
452        of the "Ring", you can use Sn and Pn to know how many "lower"
453        entries you will find. This may be useful for keeping the
454        "Address order" while gathering all the information throughout
455        the RING.
456
457        Please note that some "common" entries (as "-Unpublished-" for
458        the phone number), may have more than 254 links; so be aware
459        that Sn and Pn may (under exceptional conditions) overflow,
460        arrive at 0xff and restart from 0x00.
461
462        This should be no concern when doing a normal lookup, but
463        "statistical programs" that list all the Rings must be careful.
464
465        The proper way to check whether you have finished the RING is to
466        check the new SOfs/POfs against the first encountered one; Sn/Pn
467        should be used for reference only.
468
469
470
471        3.2.1.2. <NodeLink>
472        ~~~~~~~~~~~~~~~~~~~
473
474        The following structure is absent for points, since they do not
475        have downlinks. It's the same structure used in the <Header> for
476        <TopLink>.
477
478
479        struct _DTPNodeLnk {
480            word  ndowns;   // number of systems in lower level
481            dword FlOfs;    // DAT offset of "Lower Fido Level"
482        };
483
484
485        ndowns:
486              The number of direct downlinks.
487
488              It includes the lower level coordinators and all the
489              systems that, for some reason, are orphans of the upper
490              coordinator (not included in compilation or not existent).
491
492              Examples:
493
494              ZCs -> ZC's points
495                     independent nodes in the zone
496                     independent HCs in the zone
497                     independent NCs in the zone
498                     RCs in the zone
499
500              RCs -> RC's points
501                     independent nodes in the region
502                     independent HCs in the region
503                     NCs in the region
504
505              NCs -> NC's points
506                     independent nodes in the net
507                     HCs in the net
508
509              HCs -> HC's points
510                     nodes in the Hub
511
512             Node -> Node's points
513
514
515
516        FlOfs:
517              Offset into <NODEX>.DAT for the first direct downlink, in
518              "zone/region/net/hub/node/point" order.
519
520
521
522        3.2.2. <Raw-size>
523        ~~~~~~~~~~~~~~~~~
524
525        This is a word specifying the length of the following
526        <raw-nodelist-line> field.
527
528
529        3.2.3. <Raw-nodelist-line>
530        ~~~~~~~~~~~~~~~~~~~~~~~~~~
531
532        This is the zero terminated raw nodelist line, taken verbatim
533        from the source nodelist; neither carriage-return nor line-feed
534        is present.
535
536        REQUIREMENTs for applications that use this field:
537
538        - The line's fields must be recognized ONLY by considering the
539          comma ',' as a separator.
540
541        - Fields containing space are to be handled normally.
542
543        - Unknown qualifiers at the start of the line (the field usued
544          for Hub, Host, Region, Zone) must be accepted.
545
546        - The second field (where the node number is usually placed)
547          may contain further information and space: it must be accepted
548          without error.
549
550
551        3.3. DTP extensions
552        ~~~~~~~~~~~~~~~~~~~
553
554        The DTP format is suitable for backward compatible extensions.
555
556        If you would like new fields, please contact Alberto Pasquale
557        (2:332/504@fidonet) and/or Thomas Waldmann (2:2474/400@fidonet)
558        for discussion.
559
560        If the new field is considered useful, a draft for the new
561        version of V7+ will be issued by Alberto Pasquale.
562
563
564
565        4. <NODEX>.PDX Phone Index
566        ==========================
567
568        The purpose of the Phone Index is to allow an indexed search of
569        a system entry from its phone number.
570
571        This is especially useful with CID (caller ID) enabled systems.
572
573
574        4.1. <NODEX>.PDX format
575        ~~~~~~~~~~~~~~~~~~~~~~~
576
577        The index is a btree, just like those for the Address and SysOp
578        indices that are standard in Version 7.
579
580        Phone numbers will be indexed in the "processed" dialable form
581        (i.e. as in the V7 phone field) after removal of dashes.
582
583        Special non-numerical phone entries, including IP addresses and
584        internet domains, are indexed verbatim (the possible
585        translations operated by the nodelist compiler to allow the
586        dialing on some mailers is NOT applied to the indexed entry).
587
588        The indexing is NOT case sensitive, although the case is
589        retained in the index entries.
590
591        The index look-up must be done just the same way as for the SysOp
592        index: from the "phone number" string you obtain a pointer to
593        the corresponding entry in the <NODEX>.DAT.
594
595        Please be aware that multiple entries with the same "phone" are
596        possible, e.g for administrative akas; the Phone links in
597        <NODEX>.DTP allow easy browsing of all the "same phone" entries
598        once you have got one by index.
599
600        Currently there is no purpose in doing a case sensitive lookup;
601        in the case it becomes useful in the future, the application may
602        optionally provide settings to allow that by skipping
603        non-case-matching entries.
604
605
606        4.2. The Look-up problem
607        ~~~~~~~~~~~~~~~~~~~~~~~~
608
609        Since most ISDN devices do NOT report the CID as a "ready to
610        dial" number, some processing is required before looking up the
611        index.
612
613        Let's classify the CID reported by ISDN devices in various
614        nations into categories:
615
616        Cat A reports CID with domestic and international dialing codes,
617              local numbers have the area code.
618
619        Cat B reports CID with NO long distance dialing code,
620              local numbers have the area code.
621
622        Cat C reports CID exactly as dialable.
623
624        Cat D reports CID with NO long distance dialing code,
625              local numbers are exactly dialable.
626
627
628
629        I will now explain with an example:
630
631        I live in Modena, Italy;
632
633        Country code          : 39
634        District (area) code  : 59
635        domestic code         :  0
636        international code    : 00
637
638
639        Call Type       A-CID           B-CID           Dialable
640
641        Local           059246112       59246112        246112
642        Domestic        0513456789      513456789       0513456789
643        International   00492312345     492312345       00492312345
644
645
646                        C-CID           D-CID
647
648        Local           246112          246112
649        Domestic        0513456789      513456789
650        International   00492312345     492312345
651
652
653        Processing needed:
654
655        Category A: for local calls we need to remove the domestic and
656        district codes; domestic and international calls do not need any
657        processing.
658
659        Category B: we need to attempt finding a domestic number then,
660        in case of failure, try the international one; unfortunately the
661        CID reported by these devices allows for some ambiguity.
662
663        Category C: no processing needed.
664
665        Category D: we need to attempt finding a local number, if not
666        found we look for a domestic number, if still not found we try
667        the international one. Even more ambigous than B.
668
669
670        4.3. The ALGORITHM
671        ~~~~~~~~~~~~~~~~~~
672
673        The application must have configurable District/Area, domestic
674        and international codes; let's name them:
675
676        AreaCode
677        DomesticPrefix
678        IntlPrefix
679
680        Besides, the application must have a configurable "category",
681        which must have selections for cases A,B,C,D; let's name this
682        variable:
683
684        Category
685
686
687        Let "Search" be the name of a function that does the index
688        look-up. Please be aware that the index may contain multiple
689        entries with the same "phone" value (perhaps administrative
690        akas).
691
692        "Restore CID" means "restore the CID as got from the device".
693
694        Start:
695
696           get CID
697
698           if (category == A) {
699               If (CID begins with DomesticPrefix+AreaCode)
700                   Remove DomesticPrefix and AreaCode   // is local
701               Search
702               goto END
703           }
704
705
706           if (category == B) {
707               If (CID begins with AreaCode) {  // local or intl
708                   remove AreaCode          // try local
709                   Search
710                   if (found)
711                       goto END         // is local
712                   else {
713                       Restore CID
714                       Add IntlPrefix   // try international
715                       Search
716                       goto END
717                   }
718               } else {                 // domestic or intl
719                   Add DomesticPrefix   // try domestic
720                   Search
721                   if (found)
722                       goto END         // is domestic
723                   else {
724                       Restore CID      // try intl
725                       Add IntlPrefix
726                       Search
727                       goto END
728                   }
729
730               }
731           }
732
733
734           if (category == C) {    // no processing required
735               Search
736               goto END
737           }
738
739           if (category == D) {
740               Search             // try local
741               if (found)         // is local
742                   goto END
743               else {
744                   Add DomesticPrefix    // try domestic
745                   Search
746                   if (found)            // is domestic
747                       goto END
748                   else {                // try international
749                       Restore CID
750                       Add IntlPrefix
751                       Search
752                       goto END
753                   }
754               }
755           }
756
757
758        END: report results (pointer to NODEX.DAT or nothing found)
759
760        The Phone links in <NODEX>.DTP allow easy browsing of all
761        remaining "same phone" entries.
762
763
764        5. V7+ Semaphore
765        ================
766
767        To avoid collisions between the nodelist compiler and V7+
768        applications, a semaphore is used.
769
770        When the compiler needs exclusive access to the nodelist files,
771        it creates (if non existent) and keeps open in SH_DENYRW mode a
772        "<NODEX>.BSY" file.
773
774        When the application must access the nodelist files, it creates
775        (if non existent) and keeps open for reading in SH_DENYWR mode
776        the "<NODEX>.BSY" file.
777
778        This method allows for concurrent access by multiple programs in
779        "read" mode, while granting exclusive access to the compiler.
780
781        Please note that <NODEX>.BSY does NOT need to be deleted in case
782        of abnormal termination or power failure since it's considered
783        busy only while kept open.
784
785
786        Example for a program that must read V7+:
787
788        bsyname is the "<NODEX>.BSY" file name;
789        timeout is the timeout in seconds;
790        the file handle is returned on success, -1 on timeout
791
792
793        int waitopen (const char *bsyname, int timeout) // -1 on timeout
794        {
795          int ret = -1;
796          int i = 0;
797
798          do {
799            if (i > 0)
800              sleep (1);
801            if (access (bsyname, F_OK)) {       // file not existent
802              int handle = open (bsyname, O_WRONLY | O_CREAT, S_IWRITE);
803              if (handle != -1)
804                close (handle);
805            }
806            ret = sopen (bsyname, O_RDONLY, SH_DENYWR);
807            i ++;
808          } while ((ret == -1) && (i < timeout) &&
809                   ((errno == EACCES) || (errno == ENOENT)));
810                   // sharing violation or file not found
811            return ret;
812        }
813
814
815
816        6. Space/Time needed for V7+ database vs. usability
817        ===================================================
818
819        The V7+ DTP file may be considered redundant, since it contains
820        the entire "source" nodelist line, that duplicates some of the
821        information already present in the V7 DAT file.
822
823        Let's look at the time and space overhead involved and at the
824        gain in usability:
825
826
827        Time:
828
829        Accessing V7+ is as fast as V7, if you use the normal V7 access
830        method (and if you are NOT interested in the additional data).
831
832        If you access the additional data in the <NODEX>.DTP file, you
833        have 1 direct file access more. Nothing to worry about...
834
835        Generating a V7+ database will take somewhat longer since there
836        is more data to be written to disk, links to be set, indices to
837        be prepared; on modern machines this should not be a concern.
838
839
840        Space:
841
842        Space needed is about twice as much as for V7, but this should
843        be no concern on modern machines.
844
845
846        Usability:
847
848        - Full and complete (no lossy compression) nodelist information
849
850        - Phone Index for easy CID lookup
851
852        - SysOp/Phone/Fidonet links for easy nodelist browsing
853
854        - Backward compatible extendability
855
856
857
858        7. Sample "C" source code (taken from BT-XE)
859        ============================================
860
861        See archive v7p_src.* ...
862
863        Attention: this source code is far from being final - in fact it
864                   is the very first V7+ implementation in BT-XE and does
865                   not support all stuff that has been defined in this
866                   document. But it can read and parse V7+ data and is
867                   maybe better than no source code at all ...
868
869
870        8. History of this document
871        ===========================
872
873        Draft 1->8: preliminary thoughts about possible versions of V7+.
874
875        Draft 9: completely rewritten, this should be the final
876                 "Version_0" of V7+.
877
878        Version 0: first release version.
879
880
881