rdoff.c
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:9k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* rdoff.c    library of routines for manipulating rdoff files
  2.  *
  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.  */
  8. /* TODO: The functions in this module assume they are running
  9.  * on a little-endian machine. This should be fixed to
  10.  * make it portable.
  11.  */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <errno.h>
  16. #include "rdoff.h"
  17. #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
  18. #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), 
  19.                                        s1),s2)
  20. /* ========================================================================
  21.  * Code for memory buffers (for delayed writing of header until we know
  22.  * how long it is).
  23.  * ======================================================================== */
  24. memorybuffer * newmembuf(){
  25.   memorybuffer * t;
  26.   t = malloc(sizeof(memorybuffer));
  27.   t->length = 0;
  28.   t->next = NULL;
  29.   return t;
  30. }
  31. void membufwrite(memorybuffer *b, void *data, int bytes) {
  32.   int16 w;
  33.   long l;
  34.   if (b->next) {        /* memory buffer full - use next buffer */
  35.     membufwrite(b->next,data,bytes);
  36.     return;
  37.   }
  38.   if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
  39.       || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
  40.     
  41.     /* buffer full and no next allocated... allocate and initialise next
  42.      * buffer */
  43.     b->next = newmembuf();
  44.     membufwrite(b->next,data,bytes);
  45.   }
  46.   switch(bytes) {
  47.   case -4:              /* convert to little-endian */
  48.     l = * (long *) data ;
  49.     b->buffer[b->length++] = l & 0xFF;
  50.     l >>= 8 ;
  51.     b->buffer[b->length++] = l & 0xFF;
  52.     l >>= 8 ;
  53.     b->buffer[b->length++] = l & 0xFF;
  54.     l >>= 8 ;
  55.     b->buffer[b->length++] = l & 0xFF;
  56.     break;
  57.   case -2:
  58.     w = * (int16 *) data ;
  59.     b->buffer[b->length++] = w & 0xFF;
  60.     w >>= 8 ;
  61.     b->buffer[b->length++] = w & 0xFF;
  62.     break;
  63.   default:
  64.     while(bytes--) {
  65.       b->buffer[b->length++] = *(* (unsigned char **) &data);
  66.       (* (unsigned char **) &data)++ ;
  67.     }
  68.     break;
  69.   }
  70. }
  71. void membufdump(memorybuffer *b,FILE *fp)
  72. {
  73.   if (!b) return;
  74.   fwrite (b->buffer, 1, b->length, fp);
  75.   
  76.   membufdump(b->next,fp);
  77. }
  78. int membuflength(memorybuffer *b)
  79. {
  80.   if (!b) return 0;
  81.   return b->length + membuflength(b->next);
  82. }
  83. void freemembuf(memorybuffer *b)
  84. {
  85.   if (!b) return;
  86.   freemembuf(b->next);
  87.   free(b);
  88. }
  89. /* =========================================================================
  90.    General purpose routines and variables used by the library functions
  91.    ========================================================================= */
  92. long translatelong(long in) {           /* translate from little endian to
  93.                                            local representation */
  94.   long r;
  95.   unsigned char *i;
  96.   i = (unsigned char *)&in;
  97.   r = i[3];
  98.   r = (r << 8) + i[2];
  99.   r = (r << 8) + i[1];
  100.   r = (r << 8) + *i;
  101.   return r;
  102. }
  103. const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
  104. const char *rdf_errors[7] = {
  105.   "no error occurred","could not open file","invalid file format",
  106.   "error reading file","unknown error","header not read",
  107.   "out of memory"};
  108. int rdf_errno = 0;
  109. /* ========================================================================
  110.    The library functions
  111.    ======================================================================== */
  112. int rdfopen(rdffile *f, const char *name)
  113. {
  114.     FILE * fp;
  115.     fp = fopen(name,"rb");
  116.     if (!fp) return rdf_errno = 1; /* error 1: file open error */
  117.     return rdfopenhere(f,fp,NULL,"");
  118. }
  119. int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
  120. {
  121.   char buf[8];
  122.   long initpos;
  123.   if (translatelong(0x01020304) != 0x01020304)
  124.   { /* fix this to be portable! */
  125.     fputs("*** this program requires a little endian machinen",stderr);
  126.     fprintf(stderr,"01020304h = %08lxhn",translatelong(0x01020304));
  127.     exit(3);
  128.   }
  129.   f->fp = fp;
  130.   initpos = ftell(fp);
  131.   fread(buf,6,1,f->fp); /* read header */
  132.   buf[6] = 0;
  133.   if (strcmp(buf,RDOFFId)) {
  134.     fclose(f->fp);
  135.     return rdf_errno = 2;  /* error 2: invalid file format */
  136.   }
  137.   if (fread(&f->header_len,1,4,f->fp) != 4) {
  138.     fclose(f->fp);
  139.     return rdf_errno = 3; /* error 3: file read error */
  140.   }
  141.   f->header_ofs = ftell(f->fp);
  142.   if (fseek(f->fp,f->header_len,SEEK_CUR)) {
  143.     fclose(f->fp);
  144.     return rdf_errno = 2; /* seek past end of file...? */
  145.   }
  146.   if (fread(&f->code_len,1,4,f->fp) != 4) {
  147.     fclose(f->fp);
  148.     return rdf_errno = 3;
  149.   }
  150.   f->code_ofs = ftell(f->fp);
  151.   if (fseek(f->fp,f->code_len,SEEK_CUR)) {
  152.     fclose(f->fp);
  153.     return rdf_errno = 2;
  154.   }
  155.   if (fread(&f->data_len,1,4,f->fp) != 4) {
  156.     fclose(f->fp);
  157.     return rdf_errno = 3;
  158.   }
  159.   f->data_ofs = ftell(f->fp);
  160.   fseek(f->fp,initpos,SEEK_SET);
  161.   f->header_loc = NULL;
  162.   f->name = newstr(name);
  163.   f->refcount = refcount;
  164.   if (refcount) (*refcount)++;
  165.   return 0;
  166. }
  167. int rdfclose(rdffile *f)
  168. {
  169.     if (! f->refcount || ! *--f->refcount)
  170. fclose(f->fp);
  171.     free(f->name);
  172.     return 0;
  173. }
  174. void rdfperror(const char *app,const char *name)
  175. {
  176.   fprintf(stderr,"%s:%s: %sn",app,name,rdf_errors[rdf_errno]);
  177.   if (rdf_errno == 1 || rdf_errno == 3)
  178.   {
  179.       perror(app);
  180.   }
  181. }
  182. int rdfloadseg(rdffile *f,int segment,void *buffer)
  183. {
  184.   long fpos;
  185.   long slen;
  186.   switch(segment) {
  187.   case RDOFF_HEADER:
  188.     fpos = f->header_ofs;
  189.     slen = f->header_len;
  190.     f->header_loc = (char *)buffer;
  191.     f->header_fp = 0;
  192.     break;
  193.   case RDOFF_CODE:
  194.     fpos = f->code_ofs;
  195.     slen = f->code_len;
  196.     break;
  197.   case RDOFF_DATA:
  198.     fpos = f->data_ofs;
  199.     slen = f->data_len;
  200.     break;
  201.   default:
  202.     fpos = 0;
  203.     slen = 0;
  204.   }
  205.   if (fseek(f->fp,fpos,SEEK_SET))
  206.     return rdf_errno = 4;
  207.     
  208.   if (fread(buffer,1,slen,f->fp) != slen)
  209.     return rdf_errno = 3;
  210.   return 0;
  211. }
  212. /* Macros for reading integers from header in memory */
  213. #define RI8(v) v = f->header_loc[f->header_fp++]
  214. #define RI16(v) { v = (f->header_loc[f->header_fp] + 
  215.        (f->header_loc[f->header_fp+1] << 8)); 
  216.   f->header_fp += 2; }
  217. #define RI32(v) { v = (f->header_loc[f->header_fp] + 
  218.        (f->header_loc[f->header_fp+1] << 8) + 
  219.        (f->header_loc[f->header_fp+2] << 16) + 
  220.        (f->header_loc[f->header_fp+3] << 24)); 
  221.   f->header_fp += 4; }
  222. #define RS(str,max) { for(i=0;i<max;i++){
  223.   RI8(str[i]); if (!str[i]) break;} str[i]=0; }
  224. rdfheaderrec *rdfgetheaderrec(rdffile *f)
  225. {
  226.   static rdfheaderrec r;
  227.   int i;
  228.   if (!f->header_loc) {
  229.     rdf_errno = 5;
  230.     return NULL;
  231.   }
  232.   if (f->header_fp >= f->header_len) return 0;
  233.   RI8(r.type);
  234.   switch(r.type) {
  235.   case 1: /* Relocation record */
  236.     RI8(r.r.segment);
  237.     RI32(r.r.offset);
  238.     RI8(r.r.length);
  239.     RI16(r.r.refseg);
  240.     break;
  241.   case 2: /* Imported symbol record */
  242.     RI16(r.i.segment);
  243.     RS(r.i.label,32);
  244.     break;
  245.   case 3: /* Exported symbol record */
  246.     RI8(r.e.segment);
  247.     RI32(r.e.offset);
  248.     RS(r.e.label,32);
  249.     break;
  250.   case 4: /* DLL record */
  251.     RS(r.d.libname,127);
  252.     break;
  253.   case 5: /* BSS reservation record */
  254.     RI32(r.b.amount);
  255.     break;
  256.   default:
  257.     rdf_errno = 2; /* invalid file */
  258.     return NULL;
  259.   }
  260.   return &r;
  261. }
  262.     
  263. void rdfheaderrewind(rdffile *f)
  264. {
  265.   f->header_fp = 0;
  266. }
  267. rdf_headerbuf * rdfnewheader(void)
  268. {
  269.     return newmembuf();
  270. }
  271. int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
  272. {
  273.     switch (r->type)
  274.     {
  275.     case 1:
  276. membufwrite(h,&r->type,1);
  277. membufwrite(h,&r->r.segment,1);
  278. membufwrite(h,&r->r.offset,-4);
  279. membufwrite(h,&r->r.length,1);
  280. membufwrite(h,&r->r.refseg,-2);    /* 9 bytes written */
  281. break;
  282.     case 2: /* import */
  283. membufwrite(h,&r->type,1);
  284. membufwrite(h,&r->i.segment,-2);
  285. membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
  286. break ;
  287.     case 3: /* export */
  288. membufwrite(h,&r->type,1);
  289. membufwrite(h,&r->e.segment,1);
  290. membufwrite(h,&r->e.offset,-4);
  291. membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
  292. break ;
  293.     case 4: /* DLL */
  294. membufwrite(h,&r->type,1);
  295. membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
  296. break ;
  297.     case 5: /* BSS */
  298. membufwrite(h,&r->type,1);
  299. membufwrite(h,&r->b.amount,-4);
  300. break ;
  301.     default:
  302. return (rdf_errno = 2);
  303.     }
  304.     return 0;
  305. }
  306. int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
  307. {
  308.     long l;
  309.     fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
  310.     l = translatelong ( membuflength (h) );
  311.     fwrite (&l, 4, 1, fp);
  312.     membufdump(h, fp);
  313.     return 0; /* no error handling in here... CHANGE THIS! */
  314. }
  315. void rdfdoneheader(rdf_headerbuf * h)
  316. {
  317.     freemembuf(h);
  318. }