annotate dmd/Library.d @ 0:10317f0c89a5

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