Upgrade label functions to 64-bit
[platform/upstream/nasm.git] / output / outrdf2.c
1 /*
2  * outrdf2.c    output routines for the Netwide Assembler to produce
3  *              RDOFF version 2 format object files, which Julian originally
4  *              planned to use it in his MOSCOW operating system.
5  *
6  * The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
7  * Julian Hall. All rights reserved. The software is
8  * redistributable under the licence given in the file "Licence"
9  * distributed in the NASM archive.
10  */
11
12 #include "compiler.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <assert.h>
19 #include <inttypes.h>
20
21 #include "nasm.h"
22 #include "nasmlib.h"
23 #include "outform.h"
24
25 /* VERBOSE_WARNINGS: define this to add some extra warnings... */
26 #define VERBOSE_WARNINGS
27
28 #ifdef OF_RDF2
29
30 #include "rdoff/rdoff.h"
31
32 /* This signature is written to start of RDOFF files */
33 static const char *RDOFF2Id = RDOFF2_SIGNATURE;
34
35 /* Note that whenever a segment is referred to in the RDOFF file, its number
36  * is always half of the segment number that NASM uses to refer to it; this
37  * is because NASM only allocates even numbered segments, so as to not
38  * waste any of the 16 bits of segment number written to the file - this
39  * allows up to 65533 external labels to be defined; otherwise it would be
40  * 32764. */
41
42 #define COUNT_SEGTYPES 9
43
44 static char *segmenttypes[COUNT_SEGTYPES] = {
45     "null", "text", "code", "data",
46     "comment", "lcomment", "pcomment",
47     "symdebug", "linedebug"
48 };
49
50 static int segmenttypenumbers[COUNT_SEGTYPES] = {
51     0, 1, 1, 2, 3, 4, 5, 6, 7
52 };
53
54 /* code for managing buffers needed to separate code and data into individual
55  * sections until they are ready to be written to the file.
56  * We'd better hope that it all fits in memory else we're buggered... */
57
58 #define BUF_BLOCK_LEN 4088      /* selected to match page size (4096)
59                                  * on 80x86 machines for efficiency */
60
61 /***********************************************************************
62  * Actual code to deal with RDOFF2 ouput format begins here...
63  */
64
65 /* global variables set during the initialisation phase */
66
67 static struct SAA *seg[RDF_MAXSEGS];    /* seg 0 = code, seg 1 = data */
68 static struct SAA *header;      /* relocation/import/export records */
69
70 static FILE *ofile;
71
72 static efunc error;
73
74 static struct seginfo {
75     char *segname;
76     int segnumber;
77     uint16_t segtype;
78     uint16_t segreserved;
79     int32_t seglength;
80 } segments[RDF_MAXSEGS];
81
82 static int nsegments;
83
84 static int32_t bsslength;
85 static int32_t headerlength;
86
87 static void rdf2_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval)
88 {
89     int segtext, segdata, segbss;
90
91     (void)ldef;
92     (void)eval;
93
94     maxbits = 64;
95
96     /* set up the initial segments */
97     segments[0].segname = ".text";
98     segments[0].segnumber = 0;
99     segments[0].segtype = 1;
100     segments[0].segreserved = 0;
101     segments[0].seglength = 0;
102
103     segments[1].segname = ".data";
104     segments[1].segnumber = 1;
105     segments[1].segtype = 2;
106     segments[1].segreserved = 0;
107     segments[1].seglength = 0;
108
109     segments[2].segname = ".bss";
110     segments[2].segnumber = 2;
111     segments[2].segtype = 0xFFFF;       /* reserved - should never be produced */
112     segments[2].segreserved = 0;
113     segments[2].seglength = 0;
114
115     nsegments = 3;
116
117     ofile = fp;
118     error = errfunc;
119
120     seg[0] = saa_init(1L);
121     seg[1] = saa_init(1L);
122     seg[2] = NULL;              /* special case! */
123
124     header = saa_init(1L);
125
126     segtext = seg_alloc();
127     segdata = seg_alloc();
128     segbss = seg_alloc();
129     if (segtext != 0 || segdata != 2 || segbss != 4)
130         error(ERR_PANIC,
131               "rdf segment numbers not allocated as expected (%d,%d,%d)",
132               segtext, segdata, segbss);
133     bsslength = 0;
134     headerlength = 0;
135 }
136
137 static int32_t rdf2_section_names(char *name, int pass, int *bits)
138 {
139     int i;
140     bool err;
141     char *p, *q;
142     int code = -1;
143     int reserved = 0;
144
145     (void)pass;
146
147     /*
148      * Default is 32 bits, in the text segment.
149      */
150     if (!name) {
151         *bits = 32;
152         return 0;
153     }
154
155     /* look for segment type code following segment name */
156     p = name;
157     while (*p && !isspace(*p))
158         p++;
159     if (*p) {                   /* we're now in whitespace */
160         *p++ = '\0';
161         while (*p && isspace(80))
162             *p++ = '\0';
163     }
164     if (*p) {                   /* we're now in an attribute value */
165         /*
166          * see if we have an optional ',number' following the type code
167          */
168         if ((q = strchr(p, ','))) {
169             *q++ = '\0';
170
171             reserved = readnum(q, &err);
172             if (err) {
173                 error(ERR_NONFATAL,
174                       "value following comma must be numeric");
175                 reserved = 0;
176             }
177         }
178         /*
179          * check it against the text strings in segmenttypes
180          */
181
182         for (i = 0; i < COUNT_SEGTYPES; i++)
183             if (!nasm_stricmp(p, segmenttypes[i])) {
184                 code = segmenttypenumbers[i];
185                 break;
186             }
187         if (code == -1) {       /* didn't find anything */
188             code = readnum(p, &err);
189             if (err) {
190                 error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",
191                       p);
192                 code = 3;
193             }
194         }
195     }
196     for (i = 0; i < nsegments; i++) {
197         if (!strcmp(name, segments[i].segname)) {
198             if (code != -1 || reserved != 0)
199                 error(ERR_NONFATAL, "segment attributes specified on"
200                       " redeclaration of segment");
201             return segments[i].segnumber * 2;
202         }
203     }
204
205     /* declaring a new segment! */
206
207     if (code == -1) {
208         error(ERR_NONFATAL, "new segment declared without type code");
209         code = 3;
210     }
211     if (nsegments == RDF_MAXSEGS) {
212         error(ERR_FATAL, "reached compiled-in maximum segment limit (%d)",
213               RDF_MAXSEGS);
214         return NO_SEG;
215     }
216
217     segments[nsegments].segname = nasm_strdup(name);
218     i = seg_alloc();
219     if (i % 2 != 0)
220         error(ERR_PANIC, "seg_alloc() returned odd number");
221     segments[nsegments].segnumber = i >> 1;
222     segments[nsegments].segtype = code;
223     segments[nsegments].segreserved = reserved;
224     segments[nsegments].seglength = 0;
225
226     seg[nsegments] = saa_init(1L);
227
228     return i;
229 }
230
231 /*
232  * Write relocation record
233  */
234 static void write_reloc_rec(struct RelocRec *r)
235 {
236     char buf[4], *b;
237
238     if (r->refseg != (uint16_t) NO_SEG && (r->refseg & 1))        /* segment base ref */
239         r->type = RDFREC_SEGRELOC;
240
241     r->refseg >>= 1;            /* adjust segment nos to RDF rather than NASM */
242
243     saa_wbytes(header, &r->type, 1);
244     saa_wbytes(header, &r->reclen, 1);
245     saa_wbytes(header, &r->segment, 1);
246     b = buf;
247     WRITELONG(b, r->offset);
248     saa_wbytes(header, buf, 4);
249     saa_wbytes(header, &r->length, 1);
250     b = buf;
251     WRITESHORT(b, r->refseg);
252     saa_wbytes(header, buf, 2);
253     headerlength += r->reclen + 2;
254 }
255
256 /*
257  * Write export record
258  */
259 static void write_export_rec(struct ExportRec *r)
260 {
261     char buf[4], *b;
262
263     r->segment >>= 1;
264
265     saa_wbytes(header, &r->type, 1);
266     saa_wbytes(header, &r->reclen, 1);
267     saa_wbytes(header, &r->flags, 1);
268     saa_wbytes(header, &r->segment, 1);
269     b = buf;
270     WRITELONG(b, r->offset);
271     saa_wbytes(header, buf, 4);
272     saa_wbytes(header, r->label, strlen(r->label) + 1);
273     headerlength += r->reclen + 2;
274 }
275
276 static void write_import_rec(struct ImportRec *r)
277 {
278     char buf[4], *b;
279
280     r->segment >>= 1;
281
282     saa_wbytes(header, &r->type, 1);
283     saa_wbytes(header, &r->reclen, 1);
284     saa_wbytes(header, &r->flags, 1);
285     b = buf;
286     WRITESHORT(b, r->segment);
287     saa_wbytes(header, buf, 2);
288     saa_wbytes(header, r->label, strlen(r->label) + 1);
289     headerlength += r->reclen + 2;
290 }
291
292 /*
293  * Write BSS record
294  */
295 static void write_bss_rec(struct BSSRec *r)
296 {
297     char buf[4], *b;
298
299     saa_wbytes(header, &r->type, 1);
300     saa_wbytes(header, &r->reclen, 1);
301     b = buf;
302     WRITELONG(b, r->amount);
303     saa_wbytes(header, buf, 4);
304     headerlength += r->reclen + 2;
305 }
306
307 /*
308  * Write common variable record
309  */
310 static void write_common_rec(struct CommonRec *r)
311 {
312     char buf[4], *b;
313
314     r->segment >>= 1;
315
316     saa_wbytes(header, &r->type, 1);
317     saa_wbytes(header, &r->reclen, 1);
318     b = buf;
319     WRITESHORT(b, r->segment);
320     saa_wbytes(header, buf, 2);
321     b = buf;
322     WRITELONG(b, r->size);
323     saa_wbytes(header, buf, 4);
324     b = buf;
325     WRITESHORT(b, r->align);
326     saa_wbytes(header, buf, 2);
327     saa_wbytes(header, r->label, strlen(r->label) + 1);
328     headerlength += r->reclen + 2;
329 }
330
331 /*
332  * Write library record
333  */
334 static void write_dll_rec(struct DLLRec *r)
335 {
336     saa_wbytes(header, &r->type, 1);
337     saa_wbytes(header, &r->reclen, 1);
338     saa_wbytes(header, r->libname, strlen(r->libname) + 1);
339     headerlength += r->reclen + 2;
340 }
341
342 /*
343  * Write module name record
344  */
345 static void write_modname_rec(struct ModRec *r)
346 {
347     saa_wbytes(header, &r->type, 1);
348     saa_wbytes(header, &r->reclen, 1);
349     saa_wbytes(header, r->modname, strlen(r->modname) + 1);
350     headerlength += r->reclen + 2;
351 }
352
353 /*
354  * Handle export, import and common records.
355  */
356 static void rdf2_deflabel(char *name, int32_t segment, int64_t offset,
357                           int is_global, char *special)
358 {
359     struct ExportRec r;
360     struct ImportRec ri;
361     struct CommonRec ci;
362     static int farsym = 0;
363     static int i;
364     char symflags = 0;
365     int len;
366
367     /* Check if the label length is OK */
368     if ((len = strlen(name)) >= EXIM_LABEL_MAX) {
369         error(ERR_NONFATAL, "label size exceeds %d bytes", EXIM_LABEL_MAX);
370         return;
371     }
372     if (!len) {
373         error(ERR_NONFATAL, "zero-length label");
374         return;
375     }
376
377     if (is_global == 2) {
378         /* Common variable */
379         ci.type = RDFREC_COMMON;
380         ci.size = offset;
381         ci.segment = segment;
382         strcpy(ci.label, name);
383         ci.reclen = 9 + len;
384         ci.align = 0;
385
386         /*
387          * Check the special text to see if it's a valid number and power
388          * of two; if so, store it as the alignment for the common variable.
389          */
390         if (special) {
391             bool err;
392             ci.align = readnum(special, &err);
393             if (err)
394                 error(ERR_NONFATAL, "alignment constraint `%s' is not a"
395                       " valid number", special);
396             else if ((ci.align | (ci.align - 1)) != 2 * ci.align - 1)
397                 error(ERR_NONFATAL, "alignment constraint `%s' is not a"
398                       " power of two", special);
399         }
400         write_common_rec(&ci);
401     }
402
403     /* We don't care about local labels or fix-up hints */
404     if (is_global != 1)
405         return;
406
407     if (special) {
408         while (*special == ' ' || *special == '\t')
409             special++;
410
411         if (!nasm_strnicmp(special, "export", 6)) {
412             special += 6;
413             symflags |= SYM_GLOBAL;
414         } else if (!nasm_strnicmp(special, "import", 6)) {
415             special += 6;
416             symflags |= SYM_IMPORT;
417         }
418
419         if (*special) {
420             while (isspace(*special))
421                 special++;
422             if (!nasm_stricmp(special, "far")) {
423                 farsym = 1;
424             } else if (!nasm_stricmp(special, "near")) {
425                 farsym = 0;
426             } else if (!nasm_stricmp(special, "proc") ||
427                        !nasm_stricmp(special, "function")) {
428                 symflags |= SYM_FUNCTION;
429             } else if (!nasm_stricmp(special, "data") ||
430                        !nasm_stricmp(special, "object")) {
431                 symflags |= SYM_DATA;
432             } else
433                 error(ERR_NONFATAL, "unrecognised symbol type `%s'",
434                       special);
435         }
436     }
437
438     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
439         error(ERR_NONFATAL, "unrecognised special symbol `%s'", name);
440         return;
441     }
442
443     for (i = 0; i < nsegments; i++) {
444         if (segments[i].segnumber == segment >> 1)
445             break;
446     }
447
448     if (i >= nsegments) {       /* EXTERN declaration */
449         ri.type = farsym ? RDFREC_FARIMPORT : RDFREC_IMPORT;
450         if (symflags & SYM_GLOBAL)
451             error(ERR_NONFATAL,
452                   "symbol type conflict - EXTERN cannot be EXPORT");
453         ri.flags = symflags;
454         ri.segment = segment;
455         strcpy(ri.label, name);
456         ri.reclen = 4 + len;
457         write_import_rec(&ri);
458     } else if (is_global) {
459         r.type = RDFREC_GLOBAL; /* GLOBAL declaration */
460         if (symflags & SYM_IMPORT)
461             error(ERR_NONFATAL,
462                   "symbol type conflict - GLOBAL cannot be IMPORT");
463         r.flags = symflags;
464         r.segment = segment;
465         r.offset = offset;
466         strcpy(r.label, name);
467         r.reclen = 7 + len;
468         write_export_rec(&r);
469     }
470 }
471
472 static void membufwrite(int segment, const void *data, int bytes)
473 {
474     int i;
475     char buf[4], *b;
476
477     for (i = 0; i < nsegments; i++) {
478         if (segments[i].segnumber == segment)
479             break;
480     }
481     if (i == nsegments)
482         error(ERR_PANIC, "can't find segment %d", segment);
483
484     if (bytes < 0) {
485         b = buf;
486         if (bytes == -2)
487             WRITESHORT(b, *(int16_t *)data);
488         else
489             WRITELONG(b, *(int32_t *)data);
490         data = buf;
491         bytes = -bytes;
492     }
493     segments[i].seglength += bytes;
494     saa_wbytes(seg[i], data, bytes);
495 }
496
497 static int getsegmentlength(int segment)
498 {
499     int i;
500     for (i = 0; i < nsegments; i++) {
501         if (segments[i].segnumber == segment)
502             break;
503     }
504     if (i == nsegments)
505         error(ERR_PANIC, "can't find segment %d", segment);
506
507     return segments[i].seglength;
508 }
509
510 static void rdf2_out(int32_t segto, const void *data, uint32_t type,
511                      int32_t segment, int32_t wrt)
512 {
513     int32_t bytes = type & OUT_SIZMASK;
514     struct RelocRec rr;
515     uint8_t databuf[8], *pd;
516     int seg;
517
518     if (segto == NO_SEG) {
519         if ((type & OUT_TYPMASK) != OUT_RESERVE)
520             error(ERR_NONFATAL,
521                   "attempt to assemble code in ABSOLUTE space");
522         return;
523     }
524
525     segto >>= 1;                /* convert NASM segment no to RDF number */
526
527     for (seg = 0; seg < nsegments; seg++) {
528         if (segments[seg].segnumber == segto)
529             break;
530     }
531     if (seg >= nsegments) {
532         error(ERR_NONFATAL,
533               "specified segment not supported by rdf output format");
534         return;
535     }
536
537     if (wrt != NO_SEG) {
538         wrt = NO_SEG;           /* continue to do _something_ */
539         error(ERR_NONFATAL, "WRT not supported by rdf output format");
540     }
541
542     type &= OUT_TYPMASK;
543
544     if (segto == 2 && type != OUT_RESERVE) {
545         error(ERR_NONFATAL, "BSS segments may not be initialized");
546
547         /* just reserve the space for now... */
548
549         if (type == OUT_REL2ADR)
550             bytes = 2;
551         else
552             bytes = 4;
553         type = OUT_RESERVE;
554     }
555
556     if (type == OUT_RESERVE) {
557         if (segto == 2)         /* BSS segment space reserverd */
558             bsslength += bytes;
559         else
560             while (bytes--)
561                 membufwrite(segto, databuf, 1);
562     } else if (type == OUT_RAWDATA) {
563         if (segment != NO_SEG)
564             error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
565
566         membufwrite(segto, data, bytes);
567     } else if (type == OUT_ADDRESS) {
568
569         /* if segment == NO_SEG then we are writing an address of an
570            object within the same segment - do not produce reloc rec. */
571
572         /* FIXME - is this behaviour sane? at first glance it doesn't
573            appear to be. Must test this thoroughly...! */
574
575         if (segment != NO_SEG) {
576             /* it's an address, so we must write a relocation record */
577
578             rr.type = RDFREC_RELOC;     /* type signature */
579             rr.reclen = 8;
580             rr.segment = segto; /* segment we're currently in */
581             rr.offset = getsegmentlength(segto);        /* current offset */
582             rr.length = bytes;  /* length of reference */
583             rr.refseg = segment;        /* segment referred to */
584             write_reloc_rec(&rr);
585         }
586
587         pd = databuf;           /* convert address to little-endian */
588         if (bytes == 4)
589             WRITESHORT(pd, *(int32_t *)data);
590         else if (bytes == 8)
591             WRITEDLONG(pd, *(int64_t *)data);
592         else
593             WRITESHORT(pd, *(int32_t *)data);
594
595         membufwrite(segto, databuf, bytes);
596
597     } else if (type == OUT_REL2ADR) {
598         if (segment == segto)
599             error(ERR_PANIC, "intra-segment OUT_REL2ADR");
600
601         rr.reclen = 8;
602         rr.offset = getsegmentlength(segto);    /* current offset */
603         rr.length = 2;          /* length of reference */
604         rr.refseg = segment;    /* segment referred to (will be >>1'd) */
605
606         if (segment != NO_SEG && segment % 2) {
607             rr.type = RDFREC_SEGRELOC;
608             rr.segment = segto; /* memory base refs *aren't ever* relative! */
609             write_reloc_rec(&rr);
610
611             /* what do we put in the code? Simply the data. This should almost
612              * always be zero, unless someone's doing segment arithmetic...
613              */
614             rr.offset = *(int32_t *)data;
615         } else {
616             rr.type = RDFREC_RELOC;     /* type signature */
617             rr.segment = segto + 64;    /* segment we're currently in + rel flag */
618             write_reloc_rec(&rr);
619
620             /* work out what to put in the code: offset of the end of this operand,
621              * subtracted from any data specified, so that loader can just add
622              * address of imported symbol onto it to get address relative to end of
623              * instruction: import_address + data(offset) - end_of_instrn */
624
625             rr.offset = *(int32_t *)data - (rr.offset + bytes);
626         }
627
628         membufwrite(segto, &rr.offset, -2);
629     } else if (type == OUT_REL4ADR) {
630         if ((segment == segto) && (globalbits != 64))
631             error(ERR_PANIC, "intra-segment OUT_REL4ADR");
632         if (segment != NO_SEG && segment % 2) {
633             error(ERR_PANIC, "erm... 4 byte segment base ref?");
634         }
635
636         rr.type = RDFREC_RELOC; /* type signature */
637         rr.segment = segto + 64;        /* segment we're currently in + rel tag */
638         rr.offset = getsegmentlength(segto);    /* current offset */
639         rr.length = 4;          /* length of reference */
640         rr.refseg = segment;    /* segment referred to */
641         rr.reclen = 8;
642         write_reloc_rec(&rr);
643
644         rr.offset = *(int32_t *)data - (rr.offset + bytes);
645
646         membufwrite(segto, &rr.offset, -4);
647     }
648 }
649
650 static void rdf2_cleanup(int debuginfo)
651 {
652     int32_t l;
653     struct BSSRec bs;
654     int i;
655
656     (void)debuginfo;
657
658     /* should write imported & exported symbol declarations to header here */
659
660     /* generate the output file... */
661     fwrite(RDOFF2Id, 6, 1, ofile);      /* file type magic number */
662
663     if (bsslength != 0) {       /* reserve BSS */
664         bs.type = RDFREC_BSS;
665         bs.amount = bsslength;
666         bs.reclen = 4;
667         write_bss_rec(&bs);
668     }
669
670     /*
671      * calculate overall length of the output object
672      */
673     l = headerlength + 4;
674
675     for (i = 0; i < nsegments; i++) {
676         if (i == 2)
677             continue;           /* skip BSS segment */
678         l += 10 + segments[i].seglength;
679     }
680     l += 10;                    /* null segment */
681
682     fwriteint32_t(l, ofile);
683
684     fwriteint32_t(headerlength, ofile);
685     saa_fpwrite(header, ofile); /* dump header */
686     saa_free(header);
687
688     for (i = 0; i < nsegments; i++) {
689         if (i == 2)
690             continue;
691
692         fwriteint16_t(segments[i].segtype, ofile);
693         fwriteint16_t(segments[i].segnumber, ofile);
694         fwriteint16_t(segments[i].segreserved, ofile);
695         fwriteint32_t(segments[i].seglength, ofile);
696
697         saa_fpwrite(seg[i], ofile);
698         saa_free(seg[i]);
699     }
700
701     /* null segment - write 10 bytes of zero */
702     fwriteint32_t(0, ofile);
703     fwriteint32_t(0, ofile);
704     fwriteint16_t(0, ofile);
705
706     fclose(ofile);
707 }
708
709 static int32_t rdf2_segbase(int32_t segment)
710 {
711     return segment;
712 }
713
714 /*
715  * Handle RDOFF2 specific directives
716  */
717 static int rdf2_directive(char *directive, char *value, int pass)
718 {
719     int n;
720
721     /* Check if the name length is OK */
722     if ((n = strlen(value)) >= MODLIB_NAME_MAX) {
723         error(ERR_NONFATAL, "name size exceeds %d bytes", MODLIB_NAME_MAX);
724         return 0;
725     }
726
727     if (!strcmp(directive, "library")) {
728         if (pass == 1) {
729             struct DLLRec r;
730             r.type = RDFREC_DLL;
731             r.reclen = n + 1;
732             strcpy(r.libname, value);
733             write_dll_rec(&r);
734         }
735         return 1;
736     }
737
738     if (!strcmp(directive, "module")) {
739         if (pass == 1) {
740             struct ModRec r;
741             r.type = RDFREC_MODNAME;
742             r.reclen = n + 1;
743             strcpy(r.modname, value);
744             write_modname_rec(&r);
745         }
746         return 1;
747     }
748
749     return 0;
750 }
751
752 static void rdf2_filename(char *inname, char *outname, efunc error)
753 {
754     standard_extension(inname, outname, ".rdf", error);
755 }
756
757 static const char *rdf2_stdmac[] = {
758     "%define __SECT__ [section .text]",
759     "%imacro library 1+.nolist",
760     "[library %1]",
761     "%endmacro",
762     "%imacro module 1+.nolist",
763     "[module %1]",
764     "%endmacro",
765     "%macro __NASM_CDecl__ 1",
766     "%endmacro",
767     NULL
768 };
769
770 static int rdf2_set_info(enum geninfo type, char **val)
771 {
772     (void)type;
773     (void)val;
774     return 0;
775 }
776
777 struct ofmt of_rdf2 = {
778     "Relocatable Dynamic Object File Format v2.0",
779     "rdf",
780     NULL,
781     null_debug_arr,
782     &null_debug_form,
783     rdf2_stdmac,
784     rdf2_init,
785     rdf2_set_info,
786     rdf2_out,
787     rdf2_deflabel,
788     rdf2_section_names,
789     rdf2_segbase,
790     rdf2_directive,
791     rdf2_filename,
792     rdf2_cleanup
793 };
794
795 #endif                          /* OF_RDF2 */