Pristine Ack-5.5
[Ack-5.5.git] / util / led / archive.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 #ifndef lint
6 static char rcsid[] = "$Id: archive.c,v 3.3 1994/06/24 10:34:23 ceriel Exp $";
7 #endif
8
9 #include <arch.h>
10 #include <out.h>
11 #include <ranlib.h>
12 #include "const.h"
13 #include "debug.h"
14 #include "defs.h"
15 #include "memory.h"
16
17 #define ENDLIB          ((long)0)
18
19 extern ind_t            hard_alloc();
20
21 static struct ar_hdr    arhdr;
22
23 /*
24  * First read a long telling how many ranlib structs there are, then
25  * the structs themselves. Second read a long telling how many chars there are
26  * in the string table, then the string table itself.
27  * We keep only one ranlib table in core, so this table always starts at offset
28  * (ind_t)0 from its base.
29  */
30 static long
31 getsymdeftable()
32 {
33         register ind_t          off;
34         register struct ranlib  *ran;
35         register long           count;
36         register long           nran, nchar;
37         extern long             rd_long();
38         extern int              infile;
39
40         count = nran = rd_long(infile);
41         debug("%ld ranlib structs, ", nran, 0, 0, 0);
42         off = hard_alloc(ALLORANL, nran * sizeof(struct ranlib));
43         if (off == BADOFF)
44                 fatal("no space for ranlib structs");
45         ran = (struct ranlib *)address(ALLORANL, off);
46         rd_ranlib(infile, ran, count);
47         nchar = rd_long(infile);
48         debug("%ld ranlib chars\n", nchar, 0, 0, 0);
49         if ((off = hard_alloc(ALLORANL, nchar)) == BADOFF)
50                 fatal("no space for ranlib strings");
51         rd_bytes(infile, address(ALLORANL, off), nchar);
52         ran = (struct ranlib *)address(ALLORANL, (ind_t)0);
53         while (count--) {
54                 /*
55                  * Adjust because names are now in core, not on file.
56                  * Note that `ran_off' is measured from the beginning of the
57                  * string area, NOT from the beginning of the file.
58                  */
59                 if (ran->ran_off >= nchar)
60                         fatal("bad ranlib string offset");
61                 ran->ran_off += off;
62                 ran++;
63         }
64         return nran;
65 }
66
67 extern char     *modulname;
68
69 /*
70  * Process archive with table of contents. The table of contents tells
71  * of symbols in which module they are defined. We scan the table for
72  * symbols that are known but not yet defined. Then we extract all necessary
73  * information from the corresponding module. This module may need symbols that
74  * were defined in modules located before this one in the archive, so we
75  * scan the table again. We perform these actions as long as new symbols
76  * are defined.
77  */
78 arch()
79 {
80         long    nran;
81         bool    resolved;
82
83         nran = getsymdeftable();
84
85         savemagic();
86         do {
87                 register ind_t  ranindex;
88                 register long   count;
89
90                 debug("(re)scan ranlib table\n", 0, 0, 0, 0);
91                 ranindex = (ind_t)0;
92                 count = nran;
93                 resolved = FALSE;
94                 while (count > 0) {
95                         register struct ranlib  *ran;
96                         register char           *string;
97                         register struct outname *name;
98                         register long           pos;
99                         extern int              hash();
100                         extern struct outname   *searchname();
101
102                         ran = (struct ranlib *)address(ALLORANL, ranindex);
103                         string = address(ALLORANL, (ind_t)ran->ran_off);
104                         name = searchname(string, hash(string));
105                         if (name == (struct outname *)0 || !ISUNDEFINED(name)) {
106                                 ranindex += sizeof(struct ranlib);
107                                 count--;
108                                 continue;
109                         }
110                         seek(ran->ran_pos);
111                         get_archive_header(&arhdr);
112                         modulname = arhdr.ar_name;
113                         verbose("defines %s", string, 0, 0, 0);
114                         resolved = TRUE;
115                         /*
116                          * This archive member is going to be linked,
117                          * so we don't need to know what else it defines.
118                          * Note that we assume that all ranlib information of
119                          * one archive member is contiguous.
120                          */
121                         pos = ran->ran_pos;
122                         do {
123                                 count--; ran++;
124                                 ranindex += sizeof(struct ranlib);
125                         } while (count > 0 && ran->ran_pos == pos);
126                         notelib(pos);
127                         savehdr(&arhdr);
128                         extract();
129                 }
130         } while (resolved);
131
132         dealloc(ALLORANL);
133         notelib(ENDLIB);
134 }
135
136 /*
137  * An archive member that will be loaded is remembered by storing its position
138  * in the archive into the table of positions.
139  */
140 notelib(pos)
141         long            pos;
142 {
143         register ind_t  off;
144
145         if ((off = hard_alloc(ALLOARCH, (long)sizeof(long))) == BADOFF)
146                 fatal("no space for archive position");
147         *(long *)address(ALLOARCH, off) = pos;
148 }
149
150 /*
151  * Index of position of first archive member of next archive.
152  */
153 static ind_t            posindex = (ind_t)0;
154
155 /*
156  * Process the archive in pass 2.
157  * We walk through the table of positions telling at what byte offset the
158  * archive header + module is located, until this position is ENDLIB, meaning
159  * that we've processed all needed modules in this archive. Each group of
160  * positions of an archive is terminated with ENDLIB.
161  */
162 arch2()
163 {
164         register long   *pos;
165         register ind_t  localpos;
166
167         localpos = posindex;
168         for (   pos = (long *)address(ALLOARCH, localpos);
169                 *pos != ENDLIB;
170                 pos++, localpos += sizeof(long)
171         ) {
172                 seek(*pos);
173                 get_archive_header(&arhdr);
174                 modulname = arhdr.ar_name;
175                 debug("%s: archive member\n", modulname, 0, 0, 0);
176                 finish();
177         }
178         localpos += sizeof(long);       /* Skip ENDLIB. */
179         posindex = localpos;            /* Remember for next call. */
180 }