Pristine Ack-5.5
[Ack-5.5.git] / modules / src / object / wr.c
1 /* $Id: wr.c,v 1.13 1994/06/24 11:19:14 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /*
7  * You can choose between two strategies:
8  *      - Open the output file several times, once for each logical part, and
9  *      write to it in multiple places.
10  *      - Open the output file once and seek back and forth to each logical
11  *      part. In this case #define OUTSEEK.
12  */
13
14 #include "obj.h"
15
16 extern long             lseek();
17
18 /*
19  * Parts of the output file.
20  */
21 static long             offset[MAXSECT];
22 struct fil              __parts[NPARTS];
23
24 #ifdef OUTSEEK
25 static int              outfile;
26 static long             currpos;
27 #endif
28 int                     __sectionnr;
29 #define sectionnr       __sectionnr
30 static int              offcnt;
31
32 void
33 __wr_flush(ptr)
34         register struct fil *ptr;
35 {
36 #ifdef OUTSEEK
37         /* seek to correct position even if we aren't going to write now */
38         if (currpos != ptr->currpos) {
39                 currpos = lseek(ptr->fd, ptr->currpos, 0);
40         }
41 #endif
42         if (ptr->pnow > ptr->pbegin) {
43                 wr_bytes(ptr->fd, ptr->pbegin, (long)(ptr->pnow - ptr->pbegin));
44                 ptr->currpos += ptr->pnow - ptr->pbegin;
45 #ifdef OUTSEEK
46                 currpos = ptr->currpos;
47 #endif
48                 if (ptr < &__parts[PARTEMIT+SECTCNT]) {
49                         offset[sectionnr] = ptr->currpos;
50                 }
51         }
52         ptr->cnt = WBUFSIZ;
53         ptr->pnow = ptr->pbuf;
54         ptr->pbegin = ptr->pbuf;
55 }
56
57 static void
58 OUTWRITE(p, b, n)
59         int             p;      /* part number */
60         register char   *b;     /* buffer pointer */
61         long            n;      /* write count */
62 {
63         register struct fil *ptr = &__parts[p];
64         register char *pn = ptr->pnow;
65         register int i;
66         long m;
67
68         i = ptr->cnt;
69         if (i < WBUFSIZ) {
70                 if (n > i) {
71                         __wr_flush(ptr);
72                         wr_bytes(ptr->fd, b, (long) i);
73                         n -= i;
74                         b += i;
75                         ptr->currpos += i;
76 #ifdef OUTSEEK
77                         currpos = ptr->currpos;
78 #endif
79                         if (ptr < &__parts[PARTEMIT+SECTCNT]) {
80                                 offset[sectionnr] = ptr->currpos;
81                         }
82                 }
83                 else {
84                         i = n;
85                         ptr->cnt -= i;
86                         n = 0;
87                         while (i > 0) {
88                                 *pn++ = *b++;
89                                 i--;
90                         }
91                         ptr->pnow = pn;
92                 }
93         }
94         if (ptr->cnt == 0 || ptr->cnt == WBUFSIZ) {
95                 __wr_flush(ptr);
96                 m = n & ~(WBUFSIZ - 1);
97                 if (m != 0) {
98                         wr_bytes(ptr->fd, b, m);
99                         b += m;
100                         n &= WBUFSIZ - 1;
101                         ptr->currpos += m;
102 #ifdef OUTSEEK
103                         currpos = ptr->currpos;
104 #endif
105                         if (ptr < &__parts[PARTEMIT+SECTCNT]) {
106                                 offset[sectionnr] = ptr->currpos;
107                         }
108                 }
109                 i = n;
110                 if (i != 0) {
111                         n = 0;
112                         pn = ptr->pnow;
113                         ptr->cnt -= i;
114                         while (i > 0) {
115                                 *pn++ = *b++;
116                                 i--;
117                         }
118                         ptr->pnow = pn;
119                 }
120         }
121 }
122
123 static void
124 BEGINSEEK(p, o)
125         int             p;      /* part number */
126         long            o;      /* offset in file */
127 {
128         register struct fil *ptr = &__parts[p];
129
130 #ifdef OUTSEEK
131         ptr->fd = outfile;
132         ptr->currpos = o;
133 #else
134         ptr->currpos = lseek(ptr->fd, o, 0);
135 #endif
136         if (p >= PARTRELO) o = 0;       /* no attempt to align writes
137                                            for the time being */
138         ptr->cnt = WBUFSIZ - ((int)o & (WBUFSIZ-1));
139         ptr->pbegin = ptr->pbuf + (WBUFSIZ - ptr->cnt);
140         ptr->pnow = ptr->pbegin;
141 }
142
143
144 /*
145  * Open the output file according to the chosen strategy.
146  */
147 int
148 wr_open(f)
149         char *f;
150 {
151         register struct fil     *fdp;
152
153         close(creat(f, 0666));
154 #ifdef OUTSEEK
155         if ((outfile = open(f, 1)) < 0)
156                 return 0;
157         currpos = 0;
158 #else /* not OUTSEEK */
159         for (fdp = &__parts[PARTEMIT]; fdp < &__parts[NPARTS]; fdp++)
160                 if ((fdp->fd = open(f, 1)) < 0)
161                         return 0;
162 #endif /* not OUTSEEK */
163         offcnt = 0;
164         return 1;
165 }
166
167 void
168 wr_close()
169 {
170         register struct fil *ptr;
171
172         for (ptr = &__parts[PARTEMIT]; ptr < &__parts[NPARTS]; ptr++) {
173                 __wr_flush(ptr);
174 #ifndef OUTSEEK
175                 close(ptr->fd);
176 #endif /* not OUTSEEK */
177                 ptr->fd = -1;
178         }
179 #ifdef OUTSEEK
180         close(outfile);
181         outfile = -1;
182 #endif /* OUTSEEK */
183 }
184
185 void
186 wr_ohead(head)
187         register struct outhead *head;
188 {
189         {
190                 register long off = OFF_RELO(*head);
191
192                 BEGINSEEK(PARTEMIT, 0L);
193                 BEGINSEEK(PARTRELO, off);
194                 off += (long) head->oh_nrelo * SZ_RELO;
195                 BEGINSEEK(PARTNAME, off);
196                 off += (long) head->oh_nname * SZ_NAME;
197                 BEGINSEEK(PARTCHAR, off);
198 #ifdef SYMDBUG
199                 off += head->oh_nchar;
200                 BEGINSEEK(PARTDBUG, off);
201 #endif
202         }
203         if (BYTE_ORDER != 0x0123 || sizeof(struct outhead) != SZ_HEAD)
204         {
205                 char buf[SZ_HEAD];
206
207                 register char *c = &buf[0];
208
209                 put2(head->oh_magic, c);        c += 2;
210                 put2(head->oh_stamp, c);        c += 2;
211                 put2(head->oh_flags, c);        c += 2;
212                 put2(head->oh_nsect, c);        c += 2;
213                 put2(head->oh_nrelo, c);        c += 2;
214                 put2(head->oh_nname, c);        c += 2;
215                 put4(head->oh_nemit, c);        c += 4;
216                 put4(head->oh_nchar, c);
217                 OUTWRITE(PARTEMIT, buf, (long)SZ_HEAD);
218         }
219         else OUTWRITE(PARTEMIT, (char *)head, (long)SZ_HEAD);
220 }
221
222 void
223 wr_sect(sect, cnt)
224         register struct outsect *sect;
225         register unsigned int   cnt;
226 {
227         {       register unsigned int i = cnt;
228
229                 while (i--) {
230                         if (offcnt >= 1 && offcnt < SECTCNT) {
231                                 BEGINSEEK(PARTEMIT+offcnt, sect->os_foff);
232                         }
233                         offset[offcnt++] = sect->os_foff;
234                         sect++;
235                 }
236                 sect -= cnt;
237         }
238 #if BYTE_ORDER == 0x0123
239         if (sizeof(struct outsect) != SZ_SECT)
240 #endif
241         while (cnt)
242         {
243                 register char *c;
244                 register unsigned int i;
245
246                 i = __parts[PARTEMIT].cnt/SZ_SECT;
247                 c = __parts[PARTEMIT].pnow;
248                 if (i > cnt) i = cnt;
249                 cnt -= i;
250                 __parts[PARTEMIT].cnt -= (i*SZ_SECT);
251                 while (i--) {
252                         put4(sect->os_base, c); c += 4;
253                         put4(sect->os_size, c); c += 4;
254                         put4(sect->os_foff, c); c += 4;
255                         put4(sect->os_flen, c); c += 4;
256                         put4(sect->os_lign, c); c += 4;
257                         sect++;
258                 }
259                 __parts[PARTEMIT].pnow = c;
260                 if (cnt) {
261                         __wr_flush(&__parts[PARTEMIT]);
262                 }
263         }
264 #if BYTE_ORDER == 0x0123
265         else {
266                 OUTWRITE(PARTEMIT, (char *) sect, (long) cnt * SZ_SECT);
267         }
268 #endif
269 }
270
271 void
272 wr_outsect(s)
273         int             s;      /* section number */
274 {
275         register struct fil *ptr = &__parts[PARTEMIT + getsect(sectionnr)];
276
277         if (s != sectionnr && s >= (SECTCNT-1) && sectionnr >= (SECTCNT-1)) {
278 #ifdef OUTSEEK
279                 if (currpos != ptr->currpos) 
280                         currpos = lseek(ptr->fd, ptr->currpos, 0);
281 #endif
282                 wr_bytes(ptr->fd, ptr->pbegin, (long)(ptr->pnow - ptr->pbegin));
283                 ptr->currpos += ptr->pnow - ptr->pbegin;
284 #ifdef OUTSEEK
285                 currpos = ptr->currpos;
286 #endif
287                 offset[sectionnr] = ptr->currpos;
288                 if (offset[s] != ptr->currpos) {
289                         ptr->currpos = lseek(ptr->fd, offset[s], 0);
290 #ifdef OUTSEEK
291                         currpos = ptr->currpos;
292 #endif
293                 }
294                 ptr->cnt = WBUFSIZ - ((int)offset[s] & (WBUFSIZ-1));
295                 ptr->pbegin = ptr->pbuf + (WBUFSIZ - ptr->cnt);
296                 ptr->pnow = ptr->pbegin;
297         }
298         sectionnr = s;
299 }
300
301 /*
302  * We don't have to worry about byte order here.
303  */
304 void
305 wr_emit(emit, cnt)
306         char            *emit;
307         long            cnt;
308 {
309         OUTWRITE(PARTEMIT + getsect(sectionnr) , emit, cnt);
310 }
311
312 void
313 wr_relo(relo, cnt)
314         register struct outrelo *relo;
315         unsigned int cnt;
316 {
317
318 #if BYTE_ORDER == 0x0123
319         if (sizeof(struct outrelo) != SZ_RELO)
320 #endif
321         while (cnt)
322         {
323                 register char *c;
324                 register unsigned int i;
325
326                 i = __parts[PARTRELO].cnt/SZ_RELO;
327                 c = __parts[PARTRELO].pnow;
328                 if (i > cnt) i = cnt;
329                 cnt -= i;
330                 __parts[PARTRELO].cnt -= (i*SZ_RELO);
331                 while (i--) {
332                         *c++ = relo->or_type;
333                         *c++ = relo->or_sect;
334                         put2(relo->or_nami, c); c += 2;
335                         put4(relo->or_addr, c); c += 4;
336                         relo++;
337                 }
338                 __parts[PARTRELO].pnow = c;
339                 if (cnt) {
340                         __wr_flush(&__parts[PARTRELO]);
341                 }
342         }
343 #if BYTE_ORDER == 0x0123
344         else {
345                 OUTWRITE(PARTRELO, (char *) relo, (long) cnt * SZ_RELO);
346         }
347 #endif
348 }
349
350 void
351 wr_name(name, cnt)
352         register struct outname *name;
353         unsigned int cnt;
354 {
355 #if BYTE_ORDER == 0x0123
356         if (sizeof(struct outname) != SZ_NAME)
357 #endif
358         while (cnt)
359         {
360                 register char *c;
361                 register unsigned int i;
362
363                 i = __parts[PARTNAME].cnt/SZ_NAME;
364                 c = __parts[PARTNAME].pnow;
365                 if (i > cnt) i = cnt;
366                 cnt -= i;
367                 __parts[PARTNAME].cnt -= (i*SZ_NAME);
368                 while (i--) {
369                         put4(name->on_foff, c); c += 4;
370                         put2(name->on_type, c); c += 2;
371                         put2(name->on_desc, c); c += 2;
372                         put4(name->on_valu, c); c += 4;
373                         name++;
374                 }
375                 __parts[PARTNAME].pnow = c;
376                 if (cnt) __wr_flush(&__parts[PARTNAME]);
377         }
378 #if BYTE_ORDER == 0x0123
379         else {
380                 OUTWRITE(PARTNAME, (char *) name, (long)cnt * SZ_NAME);
381         }
382 #endif
383
384 }
385
386 void
387 wr_string(addr, len)
388         char *addr;
389         long len;
390 {
391         
392         OUTWRITE(PARTCHAR, addr, len);
393 }
394
395 #ifdef SYMDBUG
396
397 void
398 wr_dbug(buf, size)
399         char            *buf;
400         long            size;
401 {
402         OUTWRITE(PARTDBUG, buf, size);
403 }
404
405 #endif /* SYMDBUG */