Pristine Ack-5.5
[Ack-5.5.git] / mach / arm / cv / cv.c
1 /*
2  *  Conversion from ack a.out to Arthur output format.
3  *  All this really does is to output the sections, text first, 
4  *  with no header or symbol table information.
5  *
6  *  Mostly pinched from the code for the m68k2 cv.
7  *  V1.0, 08-Mar-89 AJM
8  */
9
10 #include <stdio.h>
11 #include "out.h"
12 #include "arm.h"
13
14 #define ASSERT(x) switch (2) { case 0: case (x): ; }
15
16 /*
17  * Header and section table of ack object file.
18  */
19 struct outhead  outhead;
20 struct outsect  outsect[S_MAX];
21 char            *stringarea ;
22
23 char    *ofile;
24 int     ofile_created;
25
26 char *program ;
27
28 char flag ;
29
30 #define readf(a, b, c)  fread((a), (b), (int)(c), input)
31 #define writef(a, b, c) fwrite((a), (b), (int)(c), output)
32
33 /* Output file definitions and such */
34
35 #define HDR_LENGTH      32
36
37 char hdr[HDR_LENGTH] ;
38
39 #define TEXT    0
40 #define ROM     1
41 #define DATA    2
42 #define BSS     3
43 #define LSECT   BSS+1
44 #define NSECT   LSECT+1
45
46
47 #define N_EXT   040
48 #define N_UNDEF 00
49 #define N_ABS   01
50 #define N_TEXT  02
51 #define N_DATA  03
52 #define N_BSS   04
53 #define N_FN    037
54
55 FILE            *input;
56 FILE            *output;
57
58 long align(a,b)
59         long a,b;
60 {
61         a += b - 1;
62         return a - a % b;
63 }
64  
65 int
66 follows(pa, pb)
67         register struct outsect *pa, *pb;
68 {
69         /* return 1 if pa follows pb */
70  
71         return pa->os_base == align(pb->os_base+pb->os_size, pa->os_lign);
72 }
73
74 main(argc, argv)
75         int     argc;
76         char    *argv[];
77 {
78         register int            nsect;
79         long                    magic ;
80         long                    textsize ;
81         long                    datasize ;
82         long                    ss;
83
84         ASSERT(sizeof(struct outhead) == SZ_HEAD);
85         ASSERT(sizeof(struct outsect) == SZ_SECT);
86
87         input = stdin; output = stdout;
88         program= argv[0] ;
89         if ( argc>1 && argv[1][0]=='-' ) {
90                 flag=argv[1][1] ;
91                 argc-- ; argv++ ;
92         }
93         switch (argc) {
94         case 1: break;
95         case 3: if ((output = fopen(argv[2], "w")) == (FILE *)0)
96                         fatal("Can't write %s.\n", argv[2]);
97                 ofile = argv[2];
98                 ofile_created = 1;
99                 /* FALLTHROUGH */
100         case 2: if ((input = fopen(argv[1], "r")) == (FILE *)0)
101                         fatal("Can't read %s.\n", argv[1]);
102                 break;
103         default:fatal("Usage: %s <ack object> <riscos object>.\n", argv[0]);
104         }
105         if ( !rhead(input,&outhead) )
106                 fatal("Reading header failed.\n");
107         if (BADMAGIC(outhead))
108                 fatal("Not an ack object file.\n");
109         if (outhead.oh_nrelo > 0)
110                 fprintf(stderr, "Warning: relocation information present.\n");
111         if ( outhead.oh_nsect!=LSECT && outhead.oh_nsect!=NSECT )
112                 fatal("Input file must have %d sections, not %ld\n",
113                         NSECT,outhead.oh_nsect) ;
114         for ( nsect=0 ; nsect<outhead.oh_nsect ; nsect++ )
115                 if ( !rsect(input,&outsect[nsect]) )
116                         fatal("Reading section table failed.\n");
117
118         /* A few checks */
119
120         if ( outsect[TEXT].os_base != 0x8000 )
121                 fatal("text must start at 0x8000 not at 0x%lx\n",
122                         outsect[TEXT].os_base) ;
123
124         if ( outsect[BSS].os_flen != 0 )
125                 fatal("bss space contains initialized data\n") ;
126
127         if ( ! follows(&outsect[BSS], &outsect[DATA]))
128                 fatal("bss segment must follow data segment\n") ;
129
130         if ( ! follows(& outsect[ROM], &outsect[TEXT]))
131                 fatal("rom segment must follow text\n") ;
132
133         if ( ! follows(& outsect[DATA], &outsect[ROM]))
134                 fatal("data segment must follow rom\n") ;
135
136         if ( outhead.oh_nsect==NSECT ) {
137                 if (! follows(&outsect[LSECT], &outsect[BSS]))
138                         fatal("end segment must follow bss\n") ;
139                 if ( outsect[LSECT].os_size != 0 )
140                         fatal("end segment must be empty\n") ;
141         }
142
143         /* Action at last */
144         fseek(output,0L,0);             /* Start of output file */
145         emits(&outsect[TEXT]) ;         /* Write out the text segment */
146         emits(&outsect[ROM]) ;          /* Then the rom */
147         emits(&outsect[DATA]) ;         /* Then the data */
148
149         if ( ferror(output) ) {
150                 fatal("output write error\n") ;
151         }
152         if ( ofile_created ) chmod(argv[2],0755);
153
154         ss = 0;
155         printf(" text = %ld\n",outsect[TEXT].os_size);
156         printf(" rom  = %ld\n",outsect[ROM].os_size);
157         printf(" data = %ld\n",outsect[DATA].os_size);
158         printf(" bss  = %ld\n",outsect[BSS].os_size);
159         ss += outsect[TEXT].os_size;
160         ss += outsect[ROM].os_size;
161         ss += outsect[DATA].os_size;
162         ss += outsect[BSS].os_size;
163         printf("Total memory %ld bytes, plus heap and stack\n",ss);
164
165
166         return 0;
167 }
168
169 /*
170  * Transfer the emitted byted from one file to another.
171  * and zero fill the uninitialized space
172  */
173 emits(section) struct outsect *section ; {
174         register long   n ;
175         register int    blk;
176         char            buffer[BUFSIZ];
177
178         n= section->os_flen ;
179         while (n > 0) {
180                 blk = n > BUFSIZ ? BUFSIZ : n;
181                 readf(buffer, 1, blk);
182                 writef(buffer, 1, blk);
183                 n -= blk;
184         }
185         if ( section->os_flen!=section->os_size ) {
186                 for ( n=BUFSIZ-1 ; n ; n-- ) buffer[n]=0 ;
187                 n= section->os_size - section->os_flen ;
188                 while (n > 0) {
189                         blk = n > BUFSIZ ? BUFSIZ : n;
190                         writef(buffer, 1, blk);
191                         n -= blk;
192                 }
193         }
194 }
195
196
197 rhead(f,head) struct outhead *head ; FILE *f ; {
198         char buf[SZ_HEAD] ;
199         if ( fread(buf,SZ_HEAD,1,f)!=1 ) return 0 ;
200         iconvert(buf,(char *)head,SF_HEAD) ;
201         return 1 ;
202 }
203
204 rsect(f,sect) struct outsect *sect ; FILE *f ; {
205         char buf[SZ_SECT] ;
206         if ( fread(buf,SZ_SECT,1,f)!=1 ) return 0 ;
207         iconvert(buf,(char *)sect,SF_SECT) ;
208         return 1 ;
209 }
210
211 iconvert(buf,str,fmt) char *buf, *str, *fmt ; {
212         register char *nf, *ni, *no ;
213         int last, i ;
214         long value ;
215         ni=buf ; no=str ; nf=fmt ;
216         while ( last = *nf++ ) {
217                 last -= '0' ;
218                 if ( last<1 || last >9 ) fatal("illegal out.h format string\n");
219                 value=0 ;
220                 i=last ;
221                 while ( i-- ) {
222                         value = (value<<8) + (ni[i]&0xFF) ;
223                 }
224                 switch ( last ) {
225                 case 0 : break ;
226                 case 1 : *no= value ; break ;
227                 case 2 : *(unsigned short *)no = value ; break ;
228                 case 4 : *(long *)no = value ; break ;
229                 default :
230                          fatal("illegal out.h format string\n");
231                 }
232                 ni += last ; no += last ;
233         }
234 }
235
236 /* VARARGS1 */
237 fatal(s, a1, a2)
238         char    *s;
239 {
240         fprintf(stderr,"%s: ",program) ;
241         fprintf(stderr, s, a1, a2);
242         if (ofile_created)
243                 unlink(ofile);
244         exit(-1);
245 }