NASM 0.91
[nasm/avx512.git] / rdoff / rdoff.c
blob9a969ad0388def63ce3924f1831a17825042ac77
1 /* rdoff.c library of routines for manipulating rdoff files
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 */
9 /* TODO: The functions in this module assume they are running
10 * on a little-endian machine. This should be fixed to
11 * make it portable.
14 #include <stdio.h>
15 #include <stdlib.h>
17 #include "rdoff.h"
19 /* ========================================================================
20 * Code for memory buffers (for delayed writing of header until we know
21 * how long it is).
22 * ======================================================================== */
25 memorybuffer * newmembuf(){
26 memorybuffer * t;
28 t = malloc(sizeof(memorybuffer));
30 t->length = 0;
31 t->next = NULL;
32 return t;
35 void membufwrite(memorybuffer *b, void *data, int bytes) {
36 int16 w;
37 long l;
39 if (b->next) { /* memory buffer full - use next buffer */
40 membufwrite(b->next,data,bytes);
41 return;
43 if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
44 || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
46 /* buffer full and no next allocated... allocate and initialise next
47 * buffer */
49 b->next = newmembuf();
50 membufwrite(b->next,data,bytes);
53 switch(bytes) {
54 case -4: /* convert to little-endian */
55 l = * (long *) data ;
56 b->buffer[b->length++] = l & 0xFF;
57 l >>= 8 ;
58 b->buffer[b->length++] = l & 0xFF;
59 l >>= 8 ;
60 b->buffer[b->length++] = l & 0xFF;
61 l >>= 8 ;
62 b->buffer[b->length++] = l & 0xFF;
63 break;
65 case -2:
66 w = * (int16 *) data ;
67 b->buffer[b->length++] = w & 0xFF;
68 w >>= 8 ;
69 b->buffer[b->length++] = w & 0xFF;
70 break;
72 default:
73 while(bytes--) {
74 b->buffer[b->length++] = *(* (unsigned char **) &data);
76 (* (unsigned char **) &data)++ ;
78 break;
82 void membufdump(memorybuffer *b,FILE *fp)
84 if (!b) return;
86 fwrite (b->buffer, 1, b->length, fp);
88 membufdump(b->next,fp);
91 int membuflength(memorybuffer *b)
93 if (!b) return 0;
94 return b->length + membuflength(b->next);
97 void freemembuf(memorybuffer *b)
99 if (!b) return;
100 freemembuf(b->next);
101 free(b);
104 /* =========================================================================
105 General purpose routines and variables used by the library functions
106 ========================================================================= */
108 long translatelong(long in) { /* translate from little endian to
109 local representation */
110 long r;
111 unsigned char *i;
113 i = (unsigned char *)&in;
114 r = i[3];
115 r = (r << 8) + i[2];
116 r = (r << 8) + i[1];
117 r = (r << 8) + *i;
119 return r;
122 const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
124 const char *rdf_errors[7] = {
125 "no error occurred","could not open file","invalid file format",
126 "error reading file","unknown error","header not read",
127 "out of memory"};
129 int rdf_errno = 0;
131 /* ========================================================================
132 The library functions
133 ======================================================================== */
135 int rdfopen(rdffile *f, const char *name)
137 char buf[8];
139 if (translatelong(0x01020304) != 0x01020304)
140 { /* fix this to be portable! */
141 fputs("*** this program requires a little endian machine\n",stderr);
142 fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
143 exit(3);
147 f->fp = fopen(name,"rb");
148 if (!f->fp) return rdf_errno = 1; /* error 1: file open error */
150 fread(buf,6,1,f->fp); /* read header */
151 buf[6] = 0;
153 if (strcmp(buf,RDOFFId)) {
154 fclose(f->fp);
155 return rdf_errno = 2; /* error 2: invalid file format */
158 if (fread(&f->header_len,1,4,f->fp) != 4) {
159 fclose(f->fp);
160 return rdf_errno = 3; /* error 3: file read error */
163 if (fseek(f->fp,f->header_len,SEEK_CUR)) {
164 fclose(f->fp);
165 return rdf_errno = 2; /* seek past end of file...? */
168 if (fread(&f->code_len,1,4,f->fp) != 4) {
169 fclose(f->fp);
170 return rdf_errno = 3;
173 f->code_ofs = ftell(f->fp);
174 if (fseek(f->fp,f->code_len,SEEK_CUR)) {
175 fclose(f->fp);
176 return rdf_errno = 2;
179 if (fread(&f->data_len,1,4,f->fp) != 4) {
180 fclose(f->fp);
181 return rdf_errno = 3;
184 f->data_ofs = ftell(f->fp);
185 rewind(f->fp);
186 f->header_loc = NULL;
187 return 0;
190 int rdfclose(rdffile *f)
192 fclose(f->fp);
193 return 0;
196 void rdfperror(const char *app,const char *name)
198 fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
201 int rdfloadseg(rdffile *f,int segment,void *buffer)
203 long fpos;
204 long slen;
206 switch(segment) {
207 case RDOFF_HEADER:
208 fpos = 10;
209 slen = f->header_len;
210 f->header_loc = (char *)buffer;
211 f->header_fp = 0;
212 break;
213 case RDOFF_CODE:
214 fpos = f->code_ofs;
215 slen = f->code_len;
216 break;
217 case RDOFF_DATA:
218 fpos = f->data_ofs;
219 slen = f->data_len;
220 break;
221 default:
222 fpos = 0;
223 slen = 0;
226 if (fseek(f->fp,fpos,SEEK_SET))
227 return rdf_errno = 4;
229 if (fread(buffer,1,slen,f->fp) != slen)
230 return rdf_errno = 3;
232 return 0;
235 /* Macros for reading integers from header in memory */
237 #define RI8(v) v = f->header_loc[f->header_fp++]
238 #define RI16(v) { v = (f->header_loc[f->header_fp] + \
239 (f->header_loc[f->header_fp+1] << 8)); \
240 f->header_fp += 2; }
242 #define RI32(v) { v = (f->header_loc[f->header_fp] + \
243 (f->header_loc[f->header_fp+1] << 8) + \
244 (f->header_loc[f->header_fp+2] << 16) + \
245 (f->header_loc[f->header_fp+3] << 24)); \
246 f->header_fp += 4; }
248 #define RS(str,max) { for(i=0;i<max;i++){\
249 RI8(str[i]); if (!str[i]) break;} str[i]=0; }
251 rdfheaderrec *rdfgetheaderrec(rdffile *f)
253 static rdfheaderrec r;
254 int i;
256 if (!f->header_loc) {
257 rdf_errno = 5;
258 return NULL;
261 if (f->header_fp >= f->header_len) return 0;
263 RI8(r.type);
264 switch(r.type) {
265 case 1: /* Relocation record */
266 RI8(r.r.segment);
267 RI32(r.r.offset);
268 RI8(r.r.length);
269 RI16(r.r.refseg);
270 break;
272 case 2: /* Imported symbol record */
273 RI16(r.i.segment);
274 RS(r.i.label,32);
275 break;
277 case 3: /* Exported symbol record */
278 RI8(r.e.segment);
279 RI32(r.e.offset);
280 RS(r.e.label,32);
281 break;
283 case 4: /* DLL record */
284 RS(r.d.libname,127);
285 break;
287 case 5: /* BSS reservation record */
288 RI32(r.b.amount);
289 break;
291 default:
292 rdf_errno = 2; /* invalid file */
293 return NULL;
295 return &r;
298 void rdfheaderrewind(rdffile *f)
300 f->header_fp = 0;
304 rdf_headerbuf * rdfnewheader(void)
306 return newmembuf();
309 int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
311 switch (r->type)
313 case 1:
314 membufwrite(h,&r->type,1);
315 membufwrite(h,&r->r.segment,1);
316 membufwrite(h,&r->r.offset,-4);
317 membufwrite(h,&r->r.length,1);
318 membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */
319 break;
321 case 2: /* import */
322 membufwrite(h,&r->type,1);
323 membufwrite(h,&r->i.segment,-2);
324 membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
325 break ;
327 case 3: /* export */
328 membufwrite(h,&r->type,1);
329 membufwrite(h,&r->e.segment,1);
330 membufwrite(h,&r->e.offset,-4);
331 membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
332 break ;
334 case 4: /* DLL */
335 membufwrite(h,&r->type,1);
336 membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
337 break ;
339 case 5: /* BSS */
340 membufwrite(h,&r->type,1);
341 membufwrite(h,&r->b.amount,-4);
342 break ;
344 default:
345 return (rdf_errno = 2);
347 return 0;
350 int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
352 long l;
354 fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
356 l = translatelong ( membuflength (h) );
357 fwrite (&l, 4, 1, fp);
359 membufdump(h, fp);
361 return 0; /* no error handling in here... CHANGE THIS! */
364 void rdfdoneheader(rdf_headerbuf * h)
366 freemembuf(h);