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