--- psiconv/trunk/lib/psiconv/buffer.c 2000/12/25 22:25:33 79 +++ psiconv/trunk/lib/psiconv/buffer.c 2000/12/27 02:12:23 80 @@ -27,35 +27,56 @@ #include "error.h" #include "buffer.h" +typedef struct psiconv_relocation_s { + psiconv_u32 offset; + int id; +} *psiconv_relocation; + struct psiconv_buffer_s { - psiconv_u32 base_offset; - psiconv_list data; + psiconv_list reloc_target; /* of struct relocation_s */ + psiconv_list reloc_ref; /* of struct relocation_s */ + psiconv_list data; /* of psiconv_u8 */ }; -psiconv_buffer psiconv_buffer_new(psiconv_u32 base_offset) +static psiconv_u32 unique_id = 1; + +psiconv_u32 psiconv_buffer_unique_id(void) +{ + return unique_id ++; +} + +psiconv_buffer psiconv_buffer_new(void) { psiconv_buffer buf; if (!(buf = malloc(sizeof(*buf)))) - return NULL; - if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) { - free(buf); - return NULL; - } - buf->base_offset = base_offset; + goto ERROR1; + if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) + goto ERROR2; + if (!(buf->reloc_target = psiconv_list_new( + sizeof(struct psiconv_relocation_s)))) + goto ERROR3; + if (!(buf->reloc_ref = psiconv_list_new( + sizeof(struct psiconv_relocation_s)))) + goto ERROR4; return buf; +ERROR4: + psiconv_list_free(buf->reloc_target); +ERROR3: + psiconv_list_free(buf->data); +ERROR2: + free(buf); +ERROR1: + return NULL; } void psiconv_buffer_free(psiconv_buffer buf) { + psiconv_list_free(buf->reloc_ref); + psiconv_list_free(buf->reloc_target); psiconv_list_free(buf->data); free(buf); } -psiconv_u32 psiconv_buffer_base_offset(const psiconv_buffer buf) -{ - return buf->base_offset; -} - psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf) { return psiconv_list_length(buf->data); @@ -89,5 +110,86 @@ int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra) { + int res; + psiconv_u32 i; + psiconv_relocation reloc; + + + for (i = 0; i < psiconv_list_length(extra->reloc_target); i++) { + if (!(reloc = psiconv_list_get(extra->reloc_target,i))) + return -PSICONV_E_OTHER; + reloc->offset += psiconv_list_length(buf->data); + if ((res=psiconv_list_add(buf->reloc_target,reloc))) + return res; + } + for (i = 0; i < psiconv_list_length(extra->reloc_ref); i++) { + if (!(reloc = psiconv_list_get(extra->reloc_ref,i))) + return -PSICONV_E_OTHER; + reloc->offset += psiconv_list_length(buf->data); + if ((res = psiconv_list_add(buf->reloc_ref,reloc))) + return res; + } return psiconv_list_concat(buf->data,extra->data); } + +int psiconv_buffer_resolve(psiconv_buffer buf) +{ + int res; + psiconv_u32 i,j,temp; + psiconv_relocation target,ref; + + for (i = 0; i < psiconv_list_length(buf->reloc_ref);i++) { + if (!(ref = psiconv_list_get(buf->reloc_ref,i))) + return -PSICONV_E_OTHER; + for (j = 0; j < psiconv_list_length(buf->reloc_target);j++) { + if (!(target = psiconv_list_get(buf->reloc_target,j))) + return -PSICONV_E_OTHER; + if (ref->id == target->id) { + temp = target->offset & 0xff; + if ((res = psiconv_list_replace(buf->data,ref->offset,&temp))) + return -PSICONV_E_OTHER; + temp = (target->offset >> 8) & 0xff; + if ((res = psiconv_list_replace(buf->data,ref->offset + 1,&temp))) + return -PSICONV_E_OTHER; + temp = (target->offset >> 16) & 0xff; + if ((res = psiconv_list_replace(buf->data,ref->offset + 2,&temp))) + return -PSICONV_E_OTHER; + temp = (target->offset >> 24) & 0xff; + if ((res = psiconv_list_replace(buf->data,ref->offset + 3,&temp))) + return -PSICONV_E_OTHER; + break; + } + } + if (j == psiconv_list_length(buf->reloc_target)) + return -PSICONV_E_OTHER; + } + psiconv_list_empty(buf->reloc_target); + psiconv_list_empty(buf->reloc_ref); + return -PSICONV_E_OK; +} + +int psiconv_buffer_add_reference(psiconv_buffer buf,int id) +{ + struct psiconv_relocation_s reloc; + int res,i; + psiconv_u8 data; + + reloc.offset = psiconv_list_length(buf->data); + reloc.id = id; + if ((res = psiconv_list_add(buf->reloc_ref,&reloc))) + return res; + data = 0x00; + for (i = 0; i < 4; i++) + if ((res = psiconv_list_add(buf->data,&data))) + return res; + return -PSICONV_E_OK; +} + +int psiconv_buffer_add_target(psiconv_buffer buf, int id) +{ + struct psiconv_relocation_s reloc; + + reloc.offset = psiconv_list_length(buf->data); + reloc.id = id; + return psiconv_list_add(buf->reloc_target,&reloc); +}