Pristine Ack-5.5
[Ack-5.5.git] / util / amisc / anm.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 /* $Id: anm.c,v 1.10 1994/06/24 10:13:42 ceriel Exp $ */
6 /*
7 **      print symbol tables for
8 **      ACK object files
9 **
10 **      anm [-gopruns] [name ...]
11 */
12
13 #include        "out.h"
14 #include        "arch.h"
15 #include        "ranlib.h"
16
17 #include        <stdio.h>
18 #include        <ctype.h>
19
20 int     numsort_flg;
21 int     sectsort_flg;
22 int     undef_flg;
23 int     revsort_flg = 1;
24 int     globl_flg;
25 int     nosort_flg;
26 int     arch_flg;
27 int     prep_flg;
28 int     read_error;
29 struct  outhead hbuf;
30 struct  outsect sbuf;
31 long    off;
32 char    *malloc();
33 char    *realloc();
34 long    s_base[S_MAX];  /* for specially encoded bases */
35 char    *filename;
36 int     narg;
37
38 main(argc, argv)
39 char **argv;
40 {
41
42         if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
43                 argv++;
44                 while (*++*argv) switch (**argv) {
45                 case 'n':               /* sort numerically */
46                         numsort_flg++;
47                         continue;
48
49                 case 's':               /* sort in section order */
50                         sectsort_flg++;
51                         continue;
52
53                 case 'g':               /* globl symbols only */
54                         globl_flg++;
55                         continue;
56
57                 case 'u':               /* undefined symbols only */
58                         undef_flg++;
59                         continue;
60
61                 case 'r':               /* sort in reverse order */
62                         revsort_flg = -1;
63                         continue;
64
65                 case 'p':               /* don't sort -- symbol table order */
66                         nosort_flg++;
67                         continue;
68
69                 case 'o':               /* prepend a name to each line */
70                         prep_flg++;
71                         continue;
72
73                 default:                /* oops */
74                         fprintf(stderr, "anm: invalid argument -%c\n", *argv[0]);
75                         exit(1);
76                 }
77                 argc--;
78         }
79         if (argc == 0) {
80                 argc = 1;
81                 argv[1] = "a.out";
82         }
83         narg = argc;
84
85         while(argc--) {
86                 int fd;
87
88                 filename = *++argv;
89                 if ((fd = open(filename, 0)) < 0) {
90                         fprintf(stderr, "anm: cannot open %s\n", filename);
91                         continue;
92                 }
93                 process(fd);
94                 close(fd);
95         }
96         exit(0);
97 }
98
99 extern int rd_unsigned2();
100 extern long lseek();
101 extern char *strncpy();
102
103 process(fd)
104         int     fd;
105 {
106         unsigned int    magic;
107         long            nextpos;
108         struct ar_hdr   archive_header;
109         static char     buf[sizeof(archive_header.ar_name)+1];
110
111         if (narg > 1) printf("\n%s:\n", filename);
112
113         magic = rd_unsigned2(fd);
114         switch(magic) {
115         case O_MAGIC:
116                 lseek(fd, 0L, 0);
117                 do_file(fd);
118                 break;
119         case ARMAG:
120         case AALMAG:
121                 while (rd_arhdr(fd, &archive_header)) {
122                         nextpos = lseek(fd, 0L, 1) + archive_header.ar_size;
123                         if (nextpos & 1) nextpos++;
124                         strncpy(buf,archive_header.ar_name,sizeof(archive_header.ar_name));
125                         filename = buf;
126                         if ( strcmp(filename, SYMDEF)) {
127                                 printf("\n%s:\n", filename);
128                                 do_file(fd);
129                         }
130                         lseek(fd, nextpos, 0);
131                 }
132                 break;
133         default:
134                 fprintf(stderr, "anm: %s -- bad format\n", filename);
135                 break;
136         }
137 }
138
139 do_file(fd)
140         int     fd;
141 {
142         struct  outname *nbufp = NULL;
143         struct  outname nbuf;
144         char            *cbufp;
145         long            fi_to_co;
146         long            n;
147         unsigned        readcount;
148         int             i,j;
149         int             compare();
150
151         read_error = 0;
152         rd_fdopen(fd);
153
154         rd_ohead(&hbuf);
155         if (read_error) {
156                 return;
157         }
158         if (BADMAGIC(hbuf)) {
159                 return;
160         }
161
162         n = hbuf.oh_nname;
163         if (n == 0) {
164                 fprintf(stderr, "anm: %s -- no name list\n", filename);
165                 return;
166         }
167
168         if (hbuf.oh_nchar == 0) {
169                 fprintf(stderr, "anm: %s -- no names\n", filename);
170                 return;
171         }
172         if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) {
173                 fprintf(stderr, "anm: string area too big in %s\n", filename);
174                 exit(2);
175         }
176
177         /* store special section bases ??? */
178         if (hbuf.oh_flags & HF_8086) {
179                 rd_sect(&sbuf, hbuf.oh_nsect);
180                 if (read_error) {
181                         return;
182                 }
183                 for (i=0; i<hbuf.oh_nsect; i++) {
184                         s_base[i+S_MIN] =
185                                 (sbuf.os_base>>12) & 03777760;
186                 }
187         }
188
189         if ((cbufp = (char *)malloc(readcount)) == NULL) {
190                 fprintf(stderr, "anm: out of memory on %s\n", filename);
191                 exit(2);
192         }
193         rd_string(cbufp, hbuf.oh_nchar);
194         if (read_error) {
195                 free(cbufp);
196                 return;
197         }
198
199         fi_to_co = (long) (cbufp - OFF_CHAR(hbuf));
200         i = 0;
201         while (--n >= 0) {
202                 rd_name(&nbuf, 1);
203                 if (read_error) {
204                         break;
205                 }
206
207                 if (globl_flg && (nbuf.on_type&S_EXT)==0)
208                         continue;
209
210                 if (undef_flg
211                     &&
212                     ((nbuf.on_type&S_TYP)!=S_UND || (nbuf.on_type&S_ETC)!=0))
213                         continue;
214
215                 if (nbuf.on_foff == 0) nbuf.on_mptr = 0;
216                 else nbuf.on_mptr = (char *) (nbuf.on_foff + fi_to_co);
217
218                 /* adjust value for specially encoded bases */
219                 if (hbuf.oh_flags & HF_8086) {
220                     if (((nbuf.on_type&S_ETC) == 0) ||
221                         ((nbuf.on_type&S_ETC) == S_SCT)) {
222                         j = nbuf.on_type&S_TYP;
223                         if ((j>=S_MIN) && (j<=S_MAX))
224                             nbuf.on_valu += s_base[j];
225                     }
226                 }
227
228                 if (nbufp == NULL)
229                         nbufp = (struct outname *)malloc(sizeof(struct outname));
230                 else
231                         nbufp = (struct outname *)realloc(nbufp, (i+1)*sizeof(struct outname));
232                 if (nbufp == NULL) {
233                         fprintf(stderr, "anm: out of memory on %s\n", filename);
234                         exit(2);
235                 }
236                 nbufp[i++] = nbuf;
237         }
238
239         if (nbufp && nosort_flg==0)
240                 qsort(nbufp, i, sizeof(struct outname), compare);
241
242         for (n=0; n<i; n++) {
243                 char    cs1[4];
244                 char    cs2[4];
245
246                 if (prep_flg)
247                         printf("%s:", filename);
248
249                 switch(nbufp[n].on_type&S_ETC) {
250                 case S_SCT:
251                         sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
252                         sprintf(cs2, " S");
253                         break;
254                 case S_FIL:
255                         sprintf(cs1, " -");
256                         sprintf(cs2, " F");
257                         break;
258                 case S_MOD:
259                         sprintf(cs1, " -");
260                         sprintf(cs2, " M");
261                         break;
262                 case S_COM:
263                         sprintf(cs1, " C");
264                         if (nbufp[n].on_type&S_EXT)
265                                 sprintf(cs2, " E");
266                         else
267                                 sprintf(cs2, " -");
268                         break;
269                 case 0:
270                         if (nbufp[n].on_type&S_EXT)
271                                 sprintf(cs2, " E");
272                         else
273                                 sprintf(cs2, " -");
274
275                         switch(nbufp[n].on_type&S_TYP) {
276                         case S_UND:
277                                 sprintf(cs1, " U");
278                                 break;
279                         case S_ABS:
280                                 sprintf(cs1, " A");
281                                 break;
282                         default:
283                                 sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
284                         }
285                         break;
286                 default:
287                         sprintf(cs1, "??");
288                         sprintf(cs2, " ?");
289                 }
290
291                 printf("%8lx %s %s %s\n",nbufp[n].on_valu,cs1,cs2,nbufp[n].on_mptr ? nbufp[n].on_mptr : "(NULL)");
292         }
293
294         if (nbufp)
295                 free((char *)nbufp);
296         if (cbufp)
297                 free((char *)cbufp);
298 }
299
300 compare(p1, p2)
301 struct outname  *p1, *p2;
302 {
303         int     i;
304
305         if (sectsort_flg) {
306                 if ((p1->on_type&S_TYP) > (p2->on_type&S_TYP))
307                         return(revsort_flg);
308                 if ((p1->on_type&S_TYP) < (p2->on_type&S_TYP))
309                         return(-revsort_flg);
310         }
311
312         if (numsort_flg) {
313                 if (p1->on_valu > p2->on_valu)
314                         return(revsort_flg);
315                 if (p1->on_valu < p2->on_valu)
316                         return(-revsort_flg);
317         }
318
319         if (! p1->on_mptr) {
320                 if (! p2->on_mptr) return 0;
321                 return -revsort_flg;
322         }
323         if (! p2->on_mptr) return revsort_flg;
324
325         i = strcmp(p1->on_mptr, p2->on_mptr);
326
327         if (i > 0)
328                 return(revsort_flg);
329         if (i < 0)
330                 return(-revsort_flg);
331
332         return(0);
333 }
334
335 rd_fatal()
336 {
337         fprintf(stderr,"read error on %s\n", filename);
338         read_error = 1;
339 }