source: vendor/emx/current/src/libomflib/omflibcr.c

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.1 KB
Line 
1/* omflibcr.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
2
3/* Create a new OMFLIB. */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <errno.h>
9#include "omflib0.h"
10#include <sys/omflib.h>
11
12
13struct omflib *omflib_create (const char *fname, int page_size, char *error)
14{
15 struct omflib *p;
16 FILE *f;
17
18 if (page_size < 16 || page_size > 32768
19 || (page_size & (page_size - 1)) != 0)
20 {
21 strcpy (error, "Invalid page size");
22 return NULL;
23 }
24 f = fopen (fname, "wb");
25 if (f == NULL)
26 {
27 strcpy (error, strerror (errno));
28 return NULL;
29 }
30 p = malloc (sizeof (struct omflib));
31 if (p == NULL)
32 {
33 errno = ENOMEM;
34 strcpy (error, strerror (errno));
35 fclose (f);
36 remove (fname);
37 return NULL;
38 }
39 p->f = f;
40 p->page_size = page_size;
41 p->dict_offset = 0;
42 p->dict_blocks = 0;
43 p->flags = 1;
44 p->mod_tab = NULL;
45 p->mod_alloc = 0;
46 p->mod_count = -1;
47 p->dict = NULL;
48 p->pub_tab = NULL;
49 p->pub_alloc = 0;
50 p->pub_count = 0;
51 p->output = TRUE;
52 p->state = OS_EMPTY;
53 p->mod_page = 0;
54 p->mod_name[0] = 0;
55 return p;
56}
57
58
59int omflib_header (struct omflib *p, char *error)
60{
61 fseek (p->f, 0, SEEK_SET);
62 return omflib_pad (p->f, p->page_size, TRUE, error);
63}
64
65
66static int omflib_add_dict (struct omflib *p, const char *name, int page,
67 char *error)
68{
69 int block_index, bucket_index;
70 int bv, len, bucket_count;
71 byte *block, *ptr;
72 byte buf[257];
73 int (*compare)(const void *s1, const void *s2, size_t n);
74
75 len = strlen (name);
76 if (len > 255)
77 {
78 strcpy (error, "Symbol name too long");
79 return -1;
80 }
81 buf[0] = (byte)len;
82 memcpy (buf+1, name, len);
83 omflib_hash (p, buf);
84 block_index = p->block_index;
85 bucket_index = p->bucket_index;
86 compare = (p->flags & 1 ? memcmp : memicmp);
87 bucket_count = 37;
88 block = p->dict + 512 * block_index;
89 for (;;)
90 {
91 bv = block[bucket_index];
92 if (bv == 0)
93 {
94 if (block[37] == 0xff)
95 bucket_count = 0;
96 else if (2 * block[37] + len + 4 > 512)
97 {
98 block[37] = 0xff;
99 bucket_count = 0;
100 }
101 else
102 {
103 block[bucket_index] = block[37];
104 ptr = block + 2 * block[37];
105 memcpy (ptr, buf, len+1);
106 ptr[len+1] = (byte)page;
107 ptr[len+2] = (byte)(page >> 8);
108 block[37] = (2 * block[37] + len + 3 + 1) / 2;
109 if (block[37] == 0) block[37] = 0xff;
110 return 0;
111 }
112 }
113 else
114 {
115 ptr = block + 2 * bv;
116 if (*ptr == len && compare (ptr+1, buf+1, len) == 0)
117 {
118 strcpy (error, "Symbol multiply defined: ");
119 strcat (error, name);
120 return -1;
121 }
122 }
123 if (bucket_count != 0)
124 {
125 bucket_index += p->bucket_index_delta;
126 if (bucket_index >= 37)
127 bucket_index -= 37;
128 --bucket_count;
129 }
130 if (bucket_count == 0)
131 {
132 block_index += p->block_index_delta;
133 if (block_index >= p->dict_blocks)
134 block_index -= p->dict_blocks;
135 if (block_index == p->block_index)
136 return 1;
137 bucket_count = 37;
138 block = p->dict + 512 * block_index;
139 }
140 }
141}
142
143
144static int omflib_build_dict (struct omflib *p, char *error)
145{
146 int i, ret;
147
148 p->dict = realloc (p->dict, p->dict_blocks * 512);
149 if (p->dict == NULL)
150 {
151 errno = ENOMEM;
152 return omflib_set_error (error);
153 }
154 memset (p->dict, 0, p->dict_blocks * 512);
155 for (i = 0; i < p->dict_blocks; ++i)
156 p->dict[i * 512 + 37] = 38 / 2;
157 for (i = 0; i < p->pub_count; ++i)
158 {
159 ret = omflib_add_dict (p, p->pub_tab[i].name, p->pub_tab[i].page, error);
160 if (ret != 0)
161 return ret;
162 }
163 return 0;
164}
165
166
167static unsigned isqrt (unsigned x)
168{
169 unsigned a, r, e, i;
170
171 a = r = e = 0;
172 for (i = 0; i < 32 / 2; ++i)
173 {
174 r = (r << 2) | (x >> (32-2));
175 x <<= 2; a <<= 1;
176 e = (a << 1) | 1;
177 if (r >= e)
178 {
179 r -= e;
180 a |= 1;
181 }
182 }
183 return a;
184}
185
186
187/* Speed doesn't matter here. */
188
189static int is_prime (unsigned n)
190{
191 unsigned i, q;
192
193 q = isqrt (n);
194 for (i = 3; i <= q; i += 2)
195 if (n % i == 0)
196 return 0;
197 return 1;
198}
199
200
201static unsigned next_prime (unsigned n)
202{
203 if (n <= 1)
204 return 2;
205 if (n % 2 == 0)
206 --n;
207 do
208 {
209 n += 2;
210 } while (!is_prime (n));
211 return n;
212}
213
214
215int omflib_finish (struct omflib *p, char *error)
216{
217 struct lib_header hdr;
218 int len, i, blocks;
219 unsigned prime;
220 long pos;
221 struct omf_rec rec;
222
223 if (!p->output)
224 return 0;
225 len = 0;
226 for (i = 0; i < p->pub_count; ++i)
227 len += strlen (p->pub_tab[i].name) + 3;
228 blocks = (len + 511) / 512;
229 blocks += (blocks * 128) / 512;
230 ++blocks;
231 prime = blocks;
232 for (;;)
233 {
234 prime = next_prime (prime);
235 if (prime > 65535)
236 {
237 strcpy (error, "Too many dictionary blocks");
238 return -1;
239 }
240 p->dict_blocks = prime;
241 i = omflib_build_dict (p, error);
242 if (i < 0)
243 return i;
244 if (i == 0)
245 break;
246 }
247 pos = ftell (p->f) + 3;
248 rec.rec_type = LIBEND;
249 if ((pos & 511) == 0)
250 rec.rec_len = 0;
251 else
252 rec.rec_len = (word)(((pos | 511) + 1) - pos);
253 if (fwrite (&rec, sizeof (rec), 1, p->f) != 1)
254 return omflib_set_error (error);
255 if (omflib_pad (p->f, 512, FALSE, error) != 0)
256 return -1;
257 hdr.rec_type = LIBHDR;
258 hdr.rec_len = p->page_size - 3;
259 hdr.dict_offset = ftell (p->f);
260 hdr.dict_blocks = p->dict_blocks;
261 hdr.flags = (byte)p->flags;
262 fseek (p->f, 0, SEEK_SET);
263 if (fwrite (&hdr, sizeof (hdr), 1, p->f) != 1)
264 return omflib_set_error (error);
265 fseek (p->f, hdr.dict_offset, SEEK_SET);
266 if (fwrite (p->dict, 512, p->dict_blocks, p->f) != p->dict_blocks)
267 return omflib_set_error (error);
268 return 0;
269}
270
271
272int omflib_pad (FILE *f, int size, int force, char *error)
273{
274 long pos;
275
276 pos = ftell (f);
277 while ((pos & (size-1)) != 0 || force)
278 {
279 force = FALSE;
280 if (fputc (0, f) != 0)
281 return omflib_set_error (error);
282 ++pos;
283 }
284 return 0;
285}
Note: See TracBrowser for help on using the repository browser.