root/trunk/src/libomf.c

Revision 428, 26.5 kB (checked in by walter, 2 years ago)

remove tabs, any trailing spaces

  • Property svn:eol-style set to native
Line 
1 /*
2  * Copyright (c) 1986-1995 by Symantec
3  * Copyright (c) 2000-2009 by Digital Mars
4  * All Rights Reserved
5  * http://www.digitalmars.com
6  * Written by Walter Bright
7  *
8  * This source file is made available for personal use
9  * only. The license is in /dmd/src/dmd/backendlicense.txt
10  * For any other uses, please contact Digital Mars.
11  */
12
13 // Compiler implementation of the D programming language
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <assert.h>
18
19 #include "rmem.h"
20 #include "root.h"
21 #include "stringtable.h"
22
23 #include "mars.h"
24 #include "lib.h"
25
26 #define LOG 0
27
28 Library::Library()
29 {
30     libfile = NULL;
31 }
32
33 /***********************************
34  * Set the library file name based on the output directory
35  * and the filename.
36  * Add default library file name extension.
37  */
38
39 void Library::setFilename(char *dir, char *filename)
40 {
41     char *arg = filename;
42     if (!arg || !*arg)
43     {   // Generate lib file name from first obj name
44         char *n = (char *)global.params.objfiles->data[0];
45
46         n = FileName::name(n);
47         FileName *fn = FileName::forceExt(n, global.lib_ext);
48         arg = fn->toChars();
49     }
50     if (!FileName::absolute(arg))
51         arg = FileName::combine(dir, arg);
52     FileName *libfilename = FileName::defaultExt(arg, global.lib_ext);
53
54     libfile = new File(libfilename);
55 }
56
57 void Library::write()
58 {
59     if (global.params.verbose)
60         printf("library   %s\n", libfile->name->toChars());
61
62     OutBuffer libbuf;
63     WriteLibToBuffer(&libbuf);
64
65     // Transfer image to file
66     libfile->setbuffer(libbuf.data, libbuf.offset);
67     libbuf.extractData();
68
69
70     char *p = FileName::path(libfile->name->toChars());
71     FileName::ensurePathExists(p);
72     //mem.free(p);
73
74     libfile->writev();
75 }
76
77 /*****************************************************************************/
78
79 void Library::addLibrary(void *buf, size_t buflen)
80 {
81     addObject(NULL, buf, buflen);
82 }
83
84
85 /*****************************************************************************/
86 /*****************************************************************************/
87
88 /**************************
89  * Record types:
90  */
91
92 #define RHEADR  0x6E
93 #define REGINT  0x70
94 #define REDATA  0x72
95 #define RIDATA  0x74
96 #define OVLDEF  0x76
97 #define ENDREC  0x78
98 #define BLKDEF  0x7A
99 #define BLKEND  0x7C
100 #define DEBSYM  0x7E
101 #define THEADR  0x80
102 #define LHEADR  0x82
103 #define PEDATA  0x84
104 #define PIDATA  0x86
105 #define COMENT  0x88
106 #define MODEND  0x8A
107 #define M386END 0x8B    /* 32 bit module end record */
108 #define EXTDEF  0x8C
109 #define TYPDEF  0x8E
110 #define PUBDEF  0x90
111 #define PUB386  0x91
112 #define LOCSYM  0x92
113 #define LINNUM  0x94
114 #define LNAMES  0x96
115 #define SEGDEF  0x98
116 #define GRPDEF  0x9A
117 #define FIXUPP  0x9C
118 /*#define (none)        0x9E    */
119 #define LEDATA  0xA0
120 #define LIDATA  0xA2
121 #define LIBHED  0xA4
122 #define LIBNAM  0xA6
123 #define LIBLOC  0xA8
124 #define LIBDIC  0xAA
125 #define COMDEF  0xB0
126 #define LEXTDEF 0xB4
127 #define LPUBDEF 0xB6
128 #define LCOMDEF 0xB8
129 #define CEXTDEF 0xBC
130 #define COMDAT  0xC2
131 #define LINSYM  0xC4
132 #define ALIAS   0xC6
133 #define LLNAMES 0xCA
134
135
136 #define LIBIDMAX (512 - 0x25 - 3 - 4)   // max size that will fit in dictionary
137
138
139 struct ObjModule
140 {
141     unsigned char *base;        // where are we holding it in memory
142     unsigned length;            // in bytes
143     unsigned short page;        // page module starts in output file
144     unsigned char flags;
145 #define MFgentheadr     1       // generate THEADR record
146 #define MFtheadr        2       // module name comes from THEADR record
147     char *name;                 // module name
148 };
149
150 static void parseName(unsigned char **pp, char *name)
151 {
152     unsigned char *p = *pp;
153     unsigned len = *p++;
154     if (len == 0xFF && *p == 0)  // if long name
155     {
156         len = p[1] & 0xFF;
157         len |= (unsigned)p[2] << 8;
158         p += 3;
159         assert(len <= LIBIDMAX);
160     }
161     memcpy(name, p, len);
162     name[len] = 0;
163     *pp = p + len;
164 }
165
166 static unsigned short parseIdx(unsigned char **pp)
167 {
168     unsigned char *p = *pp;
169     unsigned char c = *p++;
170
171     unsigned short idx = (0x80 & c) ? ((0x7F & c) << 8) + *p++ : c;
172     *pp = p;
173     return idx;
174 }
175
176 void Library::addSymbol(ObjModule *om, char *name, int pickAny)
177 {
178 #if LOG
179     printf("Library::addSymbol(%s, %s, %d)\n", om->name, name, pickAny);
180 #endif
181     StringValue *s = tab.insert(name, strlen(name));
182     if (!s)
183     {   // already in table
184         if (!pickAny)
185         {   s = tab.lookup(name, strlen(name));
186             assert(s);
187             ObjSymbol *os = (ObjSymbol *)s->ptrvalue;
188             error("multiple definition of %s: %s and %s: %s",
189                 om->name, name, os->om->name, os->name);
190         }
191     }
192     else
193     {
194         ObjSymbol *os = new ObjSymbol();
195         os->name = strdup(name);
196         os->om = om;
197         s->ptrvalue = (void *)os;
198
199         objsymbols.push(os);
200     }
201 }
202
203 /************************************
204  * Scan single object module for dictionary symbols.
205  * Send those symbols to Library::addSymbol().
206  */
207
208 void Library::scanObjModule(ObjModule *om)
209 {   int easyomf;
210     unsigned u;
211     unsigned char result = 0;
212     char name[LIBIDMAX + 1];
213
214     Array names;
215     names.push(NULL);           // don't use index 0
216
217     assert(om);
218     easyomf = 0;                                // assume not EASY-OMF
219     unsigned char *pend = om->base + om->length;
220
221     unsigned char *pnext;
222     for (unsigned char *p = om->base; 1; p = pnext)
223     {
224         assert(p < pend);
225         unsigned char recTyp = *p++;
226         unsigned short recLen = *(unsigned short *)p;
227         p += 2;
228         pnext = p + recLen;
229         recLen--;                               // forget the checksum
230
231         switch (recTyp)
232         {
233             case LNAMES:
234             case LLNAMES:
235                 while (p + 1 < pnext)
236                 {
237                     parseName(&p, name);
238                     names.push(strdup(name));
239                 }
240                 break;
241
242             case PUBDEF:
243                 if (easyomf)
244                     recTyp = PUB386;            // convert to MS format
245             case PUB386:
246                 if (!(parseIdx(&p) | parseIdx(&p)))
247                     p += 2;                     // skip seg, grp, frame
248                 while (p + 1 < pnext)
249                 {
250                     parseName(&p, name);
251                     p += (recTyp == PUBDEF) ? 2 : 4;    // skip offset
252                     parseIdx(&p);                               // skip type index
253                     addSymbol(om, name);
254                 }
255                 break;
256
257             case COMDAT:
258                 if (easyomf)
259                     recTyp = COMDAT+1;          // convert to MS format
260             case COMDAT+1:
261                 int pickAny = 0;
262
263                 if (*p++ & 5)           // if continuation or local comdat
264                     break;
265
266                 unsigned char attr = *p++;
267                 if (attr & 0xF0)        // attr: if multiple instances allowed
268                     pickAny = 1;
269                 p++;                    // align
270
271                 p += 2;                 // enum data offset
272                 if (recTyp == COMDAT+1)
273                     p += 2;                     // enum data offset
274
275                 parseIdx(&p);                   // type index
276
277                 if ((attr & 0x0F) == 0) // if explicit allocation
278                 {   parseIdx(&p);               // base group
279                     parseIdx(&p);               // base segment
280                 }
281
282                 unsigned idx = parseIdx(&p);    // public name index
283                 if( idx == 0 || idx >= names.dim)
284                 {
285                     //debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames));
286                     error("corrupt COMDAT");
287                     return;
288                 }
289
290                 //printf("[s] name='%s'\n",name);
291                 addSymbol(om, (char *)names.data[idx],pickAny);
292                 break;
293
294             case ALIAS:
295                 while (p + 1 < pnext)
296                 {
297                     parseName(&p, name);
298                     addSymbol(om, name);
299                     parseName(&p, name);
300                 }
301                 break;
302
303             case MODEND:
304             case M386END:
305                 result = 1;
306                 goto Ret;
307
308             case COMENT:
309                 // Recognize Phar Lap EASY-OMF format
310                 {   static unsigned char omfstr[7] =
311                         {0x80,0xAA,'8','0','3','8','6'};
312
313                     if (recLen == sizeof(omfstr))
314                     {
315                         for (unsigned i = 0; i < sizeof(omfstr); i++)
316                             if (*p++ != omfstr[i])
317                                 goto L1;
318                         easyomf = 1;
319                         break;
320                     L1: ;
321                     }
322                 }
323                 // Recognize .IMPDEF Import Definition Records
324                 {   static unsigned char omfstr[] =
325                         {0,0xA0,1};
326
327                     if (recLen >= 7)
328                     {
329                         p++;
330                         for (unsigned i = 1; i < sizeof(omfstr); i++)
331                             if (*p++ != omfstr[i])
332                                 goto L2;
333                         p++;            // skip OrdFlag field
334                         parseName(&p, name);
335                         addSymbol(om, name);
336                         break;
337                     L2: ;
338                     }
339                 }
340                 break;
341
342             default:
343                 // ignore
344                 ;
345         }
346     }
347 Ret:
348     for (u = 1; u < names.dim; u++)
349         free(names.data[u]);
350 }
351
352 /***************************************
353  * Add object module or library to the library.
354  * Examine the buffer to see which it is.
355  * If the buffer is NULL, use module_name as the file name
356  * and load the file.
357  */
358
359 void Library::addObject(const char *module_name, void *buf, size_t buflen)
360 {
361 #if LOG
362     printf("Library::addObject(%s)\n", module_name ? module_name : "");
363 #endif
364     if (!buf)
365     {   assert(module_name);
366         FileName f((char *)module_name, 0);
367         File file(&f);
368         file.readv();
369         buf = file.buffer;
370         buflen = file.len;
371         file.ref = 1;
372     }
373
374     unsigned g_page_size;
375     unsigned char *pstart = (unsigned char *)buf;
376     int islibrary = 0;
377
378     /* See if it's an OMF library.
379      * Don't go by file extension.
380      */
381
382     #pragma pack(1)
383     struct LibHeader
384     {
385         unsigned char       recTyp;      // 0xF0
386         unsigned short      pagesize;
387         long                lSymSeek;
388         unsigned short      ndicpages;
389         unsigned char       flags;
390     };
391     #pragma pack()
392
393     /* Determine if it is an OMF library, an OMF object module,
394      * or something else.
395      */
396     if (buflen < sizeof(LibHeader))
397     {
398       Lcorrupt:
399         error("corrupt object module");
400     }
401     LibHeader *lh = (LibHeader *)buf;
402     if (lh->recTyp == 0xF0)
403     {   /* OMF library
404          * The modules are all at buf[g_page_size .. lh->lSymSeek]
405          */
406         islibrary = 1;
407         g_page_size = lh->pagesize + 3;
408         buf = (void *)(pstart + g_page_size);
409         if (lh->lSymSeek > buflen ||
410             g_page_size > buflen)
411             goto Lcorrupt;
412         buflen = lh->lSymSeek - g_page_size;
413     }
414     else if (lh->recTyp == '!' && memcmp(lh, "!<arch>\n", 8) == 0)
415     {
416         error("COFF libraries not supported");
417         return;
418     }
419     else
420     {   // Not a library, assume OMF object module
421         g_page_size = 16;
422     }
423
424     /* Split up the buffer buf[0..buflen] into multiple object modules,
425      * each aligned on a g_page_size boundary.
426      */
427
428     ObjModule *om = NULL;
429     int first_module    = 1;
430
431     unsigned char *p = (unsigned char *)buf;
432     unsigned char *pend = p + buflen;
433     unsigned char *pnext;
434     for (; p < pend; p = pnext)         // for each OMF record
435     {
436         if (p + 3 >= pend)
437             goto Lcorrupt;
438         unsigned char recTyp = *p;
439         unsigned short recLen = *(unsigned short *)(p + 1);
440         pnext = p + 3 + recLen;
441         if (pnext > pend)
442             goto Lcorrupt;
443         recLen--;                          /* forget the checksum */
444
445         switch (recTyp)
446         {
447             case LHEADR :
448             case THEADR :
449                 if (!om)
450                 {   char name[LIBIDMAX + 1];
451                     om = new ObjModule();
452                     om->flags = 0;
453                     om->base = p;
454                     p += 3;
455                     parseName(&p, name);
456                     if (first_module && module_name && !islibrary)
457                     {   // Remove path and extension
458                         om->name = strdup(FileName::name(module_name));
459                         char *ext = FileName::ext(om->name);
460                         if (ext)
461                             ext[-1] = 0;
462                     }
463                     else
464                     {   /* Use THEADR name as module name,
465                          * removing path and extension.
466                          */
467                         om->name = strdup(FileName::name(name));
468                         char *ext = FileName::ext(om->name);
469                         if (ext)
470                             ext[-1] = 0;
471
472                         om->flags |= MFtheadr;
473                     }
474                     if (strcmp(name, "C") == 0)    // old C compilers did this
475                     {   om->flags |= MFgentheadr;  // generate our own THEADR
476                         om->base = pnext;          // skip past THEADR
477                     }
478                     objmodules.push(om);
479                     first_module = 0;
480                 }
481                 break;
482
483             case MODEND :
484             case M386END:
485                 if (om)
486                 {   om->page = (om->base - pstart) / g_page_size;
487                     om->length = pnext - om->base;
488                     om = NULL;
489                 }
490                 // Round up to next page
491                 unsigned t = pnext - pstart;
492                 t = (t + g_page_size - 1) & ~(unsigned)(g_page_size - 1);
493                 pnext = pstart + t;
494                 break;
495
496             default:
497                 // ignore
498                 ;
499         }
500     }
501
502     if (om)
503         goto Lcorrupt;          // missing MODEND record
504 }
505
506
507 /*****************************************************************************/
508 /*****************************************************************************/
509
510 typedef int (__cdecl * cmpfunc_t)(const void *,const void *);
511
512 extern "C" int NameCompare(ObjSymbol **p1, ObjSymbol **p2)
513 {
514     return strcmp((*p1)->name, (*p2)->name);
515 }
516
517 #define HASHMOD     0x25
518 #define BUCKETPAGE  512
519 #define BUCKETSIZE  (BUCKETPAGE - HASHMOD - 1)
520
521
522 /***********************************
523  * Calculates number of pages needed for dictionary
524  * Returns:
525  *      number of pages
526  */
527
528 unsigned short Library::numDictPages(unsigned padding)
529 {
530     unsigned short      ndicpages;
531     unsigned short      bucksForHash;
532     unsigned short      bucksForSize;
533     unsigned symSize = 0;
534
535     for (int i = 0; i < objsymbols.dim; i++)
536     {   ObjSymbol *s = (ObjSymbol *)objsymbols.data[i];
537
538         symSize += ( strlen(s->name) + 4 ) & ~1;
539     }
540
541     for (int i = 0; i < objmodules.dim; i++)
542     {   ObjModule *om = (ObjModule *)objmodules.data[i];
543
544         size_t len = strlen(om->name);
545         if (len > 0xFF)
546             len += 2;                   // Digital Mars long name extension
547         symSize += ( len + 4 + 1 ) & ~1;
548     }
549
550     bucksForHash = (objsymbols.dim + objmodules.dim + HASHMOD - 3) /
551                 (HASHMOD - 2);
552     bucksForSize = (symSize + BUCKETSIZE - padding - padding - 1) /
553                 (BUCKETSIZE - padding);
554
555     ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize;
556     //printf("ndicpages = %u\n",ndicpages);
557
558     // Find prime number greater than ndicpages
559     static unsigned primes[] =
560     { 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,
561       47,53,59,61,67,71,73,79,83,89,97,101,103,
562       107,109,113,127,131,137,139,149,151,157,
563       163,167,173,179,181,191,193,197,199,211,
564       223,227,229,233,239,241,251,257,263,269,
565       271,277,281,283,293,307,311,313,317,331,
566       337,347,349,353,359,367,373,379,383,389,
567       397,401,409,419,421,431,433,439,443,449,
568       457,461,463,467,479,487,491,499,503,509,
569       //521,523,541,547,
570       0
571     };
572
573     for (int i = 0; 1; i++)
574     {
575         if ( primes[i] == 0 )
576         {   // Quick and easy way is out.
577             // Now try and find first prime number > ndicpages
578             unsigned prime;
579
580             for (prime = (ndicpages + 1) | 1; 1; prime += 2)
581             {   // Determine if prime is prime
582                 for (unsigned u = 3; u < prime / 2; u += 2)
583                 {
584                     if ((prime / u) * u == prime)
585                         goto L1;
586                 }
587                 break;
588
589             L1: ;
590             }
591             ndicpages = prime;
592             break;
593         }
594
595         if (primes[i] > ndicpages)
596         {
597             ndicpages = primes[i];
598             break;
599         }
600     }
601
602     return ndicpages;
603 }
604
605
606 /*******************************************
607  * Write a single entry into dictionary.
608  * Returns:
609  *      0       failure
610  */
611
612 static int EnterDict( unsigned char *bucketsP, unsigned short ndicpages, unsigned char *entry, unsigned entrylen )
613 {
614     unsigned short      uStartIndex;
615     unsigned short      uStep;
616     unsigned short      uStartPage;
617     unsigned short      uPageStep;
618     unsigned short      uIndex;
619     unsigned short      uPage;
620     unsigned short      n;
621     unsigned            u;
622     unsigned            nbytes;
623     unsigned char       *aP;
624     unsigned char       *zP;
625
626     aP = entry;
627     zP = aP + entrylen;         // point at last char in identifier
628
629     uStartPage  = 0;
630     uPageStep   = 0;
631     uStartIndex = 0;
632     uStep       = 0;
633
634     u = entrylen;
635     while ( u-- )
636     {
637         uStartPage  = _rotl( uStartPage,  2 ) ^ ( *aP   | 0x20 );
638         uStep       = _rotr( uStep,       2 ) ^ ( *aP++ | 0x20 );
639         uStartIndex = _rotr( uStartIndex, 2 ) ^ ( *zP   | 0x20 );
640         uPageStep   = _rotl( uPageStep,   2 ) ^ ( *zP-- | 0x20 );
641     }
642
643     uStartPage %= ndicpages;
644     uPageStep  %= ndicpages;
645     if ( uPageStep == 0 )
646         uPageStep++;
647     uStartIndex %= HASHMOD;
648     uStep       %= HASHMOD;
649     if ( uStep == 0 )
650         uStep++;
651
652     uPage = uStartPage;
653     uIndex = uStartIndex;
654
655     // number of bytes in entry
656     nbytes = 1 + entrylen + 2;
657     if (entrylen > 255)
658         nbytes += 2;
659
660     while (1)
661     {
662         aP = &bucketsP[uPage * BUCKETPAGE];
663         uStartIndex = uIndex;
664         while (1)
665         {
666             if ( 0 == aP[ uIndex ] )
667             {
668                 // n = next available position in this page
669                 n = aP[ HASHMOD ] << 1;
670                 assert(n > HASHMOD);
671
672                 // if off end of this page
673                 if (n + nbytes > BUCKETPAGE )
674                 {   aP[ HASHMOD ] = 0xFF;
675                     break;                      // next page
676                 }
677                 else
678                 {
679                     aP[ uIndex ] = n >> 1;
680                     memcpy( (aP + n), entry, nbytes );
681                     aP[ HASHMOD ] += (nbytes + 1) >> 1;
682                     if (aP[HASHMOD] == 0)
683                         aP[HASHMOD] = 0xFF;
684                     return 1;
685                 }
686             }
687             uIndex += uStep;
688             uIndex %= 0x25;
689             /*if (uIndex > 0x25)
690                 uIndex -= 0x25;*/
691             if( uIndex == uStartIndex )
692                 break;
693         }
694         uPage += uPageStep;
695         if (uPage >= ndicpages)
696             uPage -= ndicpages;
697         if( uPage == uStartPage )
698             break;
699     }
700
701     return 0;
702 }
703
704 /*******************************************
705  * Write the module and symbol names to the dictionary.
706  * Returns:
707  *      0       failure
708  */
709
710 int Library::FillDict(unsigned char *bucketsP, unsigned short ndicpages)
711 {
712     unsigned char entry[4 + LIBIDMAX + 2 + 1];
713
714     //printf("FillDict()\n");
715
716     // Add each of the module names
717     for (int i = 0; i < objmodules.dim; i++)
718     {   ObjModule *om = (ObjModule *)objmodules.data[i];
719
720         unsigned short n = strlen( om->name );
721         if (n > 255)
722         {   entry[0] = 0xFF;
723             entry[1] = 0;
724             *(unsigned short *)(entry + 2) = n + 1;
725             memcpy(entry + 4, om->name, n);
726             n += 3;
727         }
728         else
729         {   entry[ 0 ] = 1 + n;
730             memcpy(entry + 1, om->name, n );
731         }
732         entry[ n + 1 ] = '!';
733         *((unsigned short *)( n + 2 + entry )) = om->page;
734         if ( n & 1 )
735             entry[ n + 2 + 2 ] = 0;
736         if ( !EnterDict( bucketsP, ndicpages, entry, n + 1 ) )
737             return 0;
738     }
739
740     // Sort the symbols
741     qsort( objsymbols.data, objsymbols.dim, 4, (cmpfunc_t)NameCompare );
742
743     // Add each of the symbols
744     for (int i = 0; i < objsymbols.dim; i++)
745     {   ObjSymbol *os = (ObjSymbol *)objsymbols.data[i];
746
747         unsigned short n = strlen( os->name );
748         if (n > 255)
749         {   entry[0] = 0xFF;
750             entry[1] = 0;
751             *(unsigned short *)(entry + 2) = n;
752             memcpy(entry + 4, os->name, n);
753             n += 3;
754         }
755         else
756         {   entry[ 0 ] = n;
757             memcpy( entry + 1, os->name, n );
758         }
759         *((unsigned short *)( n + 1 + entry )) = os->om->page;
760         if ( (n & 1) == 0 )
761             entry[ n + 3] = 0;
762         if ( !EnterDict( bucketsP, ndicpages, entry, n ) )
763         {
764             return 0;
765         }
766     }
767     return 1;
768 }
769
770
771 /**********************************************
772  * Create and write library to libbuf.
773  * The library consists of:
774  *      library header
775  *      object modules...
776  *      dictionary header
777  *      dictionary pages...
778  */
779
780 void Library::WriteLibToBuffer(OutBuffer *libbuf)
781 {
782     /* Scan each of the object modules for symbols
783      * to go into the dictionary
784      */
785     for (int i = 0; i < objmodules.dim; i++)
786     {   ObjModule *om = (ObjModule *)objmodules.data[i];
787
788         scanObjModule(om);
789     }
790
791     unsigned g_page_size = 16;
792
793     /* Calculate page size so that the number of pages
794      * fits in 16 bits. This is because object modules
795      * are indexed by page number, stored as an unsigned short.
796      */
797     while (1)
798     {
799       Lagain:
800 #if LOG
801         printf("g_page_size = %d\n", g_page_size);
802 #endif
803         unsigned offset = g_page_size;
804
805         for (int i = 0; i < objmodules.dim; i++)
806         {   ObjModule *om = (ObjModule *)objmodules.data[i];
807
808             unsigned page = offset / g_page_size;
809             if (page > 0xFFFF)
810             {   // Page size is too small, double it and try again
811                 g_page_size *= 2;
812                 goto Lagain;
813             }
814
815             // Write out the object module m
816             if (om->flags & MFgentheadr)                // if generate THEADR record
817             {
818                 size_t size = strlen(om->name);
819                 assert(size <= LIBIDMAX);
820
821                 offset += size + 5;
822                 //offset += om->length - (size + 5);
823                 offset += om->length;
824             }
825             else
826                 offset += om->length;
827
828             // Round the size of the file up to the next page size
829             // by filling with 0s
830             unsigned n = (g_page_size - 1) & offset;
831             if (n)
832                 offset += g_page_size - n;
833         }
834         break;
835     }
836
837
838     /* Leave one page of 0s at start as a dummy library header.
839      * Fill it in later with the real data.
840      */
841     libbuf->fill0(g_page_size);
842
843     /* Write each object module into the library
844      */
845     for (int i = 0; i < objmodules.dim; i++)
846     {   ObjModule *om = (ObjModule *)objmodules.data[i];
847
848         unsigned page = libbuf->offset / g_page_size;
849         assert(page <= 0xFFFF);
850         om->page = page;
851
852         // Write out the object module om
853         if (om->flags & MFgentheadr)            // if generate THEADR record
854         {
855             unsigned size = strlen(om->name);
856             unsigned char header[4 + LIBIDMAX + 1];
857
858             header [0] = THEADR;
859             header [1] = 2 + size;
860             header [2] = 0;
861             header [3] = size;
862             assert(size <= 0xFF - 2);
863
864             memcpy(4 + header, om->name, size);
865
866             // Compute and store record checksum
867             unsigned n = size + 4;
868             unsigned char checksum = 0;
869             unsigned char *p = header;
870             while (n--)
871             {   checksum -= *p;
872                 p++;
873             }
874             *p = checksum;
875
876             libbuf->write(header, size + 5);
877             //libbuf->write(om->base, om->length - (size + 5));
878             libbuf->write(om->base, om->length);
879         }
880         else
881             libbuf->write(om->base, om->length);
882
883         // Round the size of the file up to the next page size
884         // by filling with 0s
885         unsigned n = (g_page_size - 1) & libbuf->offset;
886         if (n)
887             libbuf->fill0(g_page_size - n);
888     }
889
890     // File offset of start of dictionary
891     unsigned offset = libbuf->offset;
892
893     // Write dictionary header, then round it to a BUCKETPAGE boundary
894     unsigned short size = (BUCKETPAGE - ((short)offset + 3)) & (BUCKETPAGE - 1);
895     libbuf->writeByte(0xF1);
896     libbuf->writeword(size);
897     libbuf->fill0(size);
898
899     // Create dictionary
900     unsigned char *bucketsP = NULL;
901     unsigned short ndicpages;
902     unsigned short padding = 32;
903     for (;;)
904     {
905         ndicpages = numDictPages(padding);
906
907 #if LOG
908         printf("ndicpages = %d\n", ndicpages);
909 #endif
910         // Allocate dictionary
911         if (bucketsP)
912             bucketsP = (unsigned char *)realloc(bucketsP, ndicpages * BUCKETPAGE);
913         else
914             bucketsP = (unsigned char *)malloc(ndicpages * BUCKETPAGE);
915         assert(bucketsP);
916         memset(bucketsP, 0, ndicpages * BUCKETPAGE);
917         for (unsigned u = 0; u < ndicpages; u++)
918         {
919             // 'next available' slot
920             bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1;
921         }
922
923         if (FillDict(bucketsP, ndicpages))
924             break;
925         padding += 16;      // try again with more margins
926     }
927
928     // Write dictionary
929     libbuf->write(bucketsP, ndicpages * BUCKETPAGE);
930     if (bucketsP)
931         free(bucketsP);
932
933     // Create library header
934     #pragma pack(1)
935     struct Libheader
936     {
937         unsigned char   recTyp;
938         unsigned short  recLen;
939         long            trailerPosn;
940         unsigned short  ndicpages;
941         unsigned char   flags;
942         char            filler[ 6 ];
943     };
944     #pragma pack()
945
946     Libheader libHeader;
947     memset(&libHeader, 0, sizeof(Libheader));
948     libHeader.recTyp = 0xF0;
949     libHeader.recLen  = 0x0D;
950     libHeader.trailerPosn = offset + (3 + size);
951     libHeader.recLen = g_page_size - 3;
952     libHeader.ndicpages = ndicpages;
953     libHeader.flags = 1;                // always case sensitive
954
955     // Write library header at start of buffer
956     memcpy(libbuf->data, &libHeader, sizeof(libHeader));
957 }
Note: See TracBrowser for help on using the browser.