… | |
… | |
25 | |
25 | |
26 | #include "list.h" |
26 | #include "list.h" |
27 | #include "error.h" |
27 | #include "error.h" |
28 | #include "buffer.h" |
28 | #include "buffer.h" |
29 | |
29 | |
|
|
30 | #ifdef DMALLOC |
|
|
31 | #include <dmalloc.h> |
|
|
32 | #endif |
|
|
33 | |
|
|
34 | typedef struct psiconv_relocation_s { |
|
|
35 | psiconv_u32 offset; |
|
|
36 | int id; |
|
|
37 | } *psiconv_relocation; |
|
|
38 | |
30 | struct psiconv_buffer_s { |
39 | struct psiconv_buffer_s { |
31 | psiconv_u32 base_offset; |
40 | psiconv_list reloc_target; /* of struct relocation_s */ |
32 | psiconv_list data; |
41 | psiconv_list reloc_ref; /* of struct relocation_s */ |
|
|
42 | psiconv_list data; /* of psiconv_u8 */ |
33 | }; |
43 | }; |
34 | |
44 | |
35 | psiconv_buffer psiconv_buffer_new(psiconv_u32 base_offset) |
45 | static psiconv_u32 unique_id = 1; |
|
|
46 | |
|
|
47 | psiconv_u32 psiconv_buffer_unique_id(void) |
|
|
48 | { |
|
|
49 | return unique_id ++; |
|
|
50 | } |
|
|
51 | |
|
|
52 | psiconv_buffer psiconv_buffer_new(void) |
36 | { |
53 | { |
37 | psiconv_buffer buf; |
54 | psiconv_buffer buf; |
38 | if (!(buf = malloc(sizeof(*buf)))) |
55 | if (!(buf = malloc(sizeof(*buf)))) |
39 | return NULL; |
56 | goto ERROR1; |
40 | if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) { |
57 | if (!(buf->data = psiconv_list_new(sizeof(psiconv_u8)))) |
41 | free(buf); |
58 | goto ERROR2; |
42 | return NULL; |
59 | if (!(buf->reloc_target = psiconv_list_new( |
43 | } |
60 | sizeof(struct psiconv_relocation_s)))) |
44 | buf->base_offset = base_offset; |
61 | goto ERROR3; |
|
|
62 | if (!(buf->reloc_ref = psiconv_list_new( |
|
|
63 | sizeof(struct psiconv_relocation_s)))) |
|
|
64 | goto ERROR4; |
45 | return buf; |
65 | return buf; |
|
|
66 | ERROR4: |
|
|
67 | psiconv_list_free(buf->reloc_target); |
|
|
68 | ERROR3: |
|
|
69 | psiconv_list_free(buf->data); |
|
|
70 | ERROR2: |
|
|
71 | free(buf); |
|
|
72 | ERROR1: |
|
|
73 | return NULL; |
46 | } |
74 | } |
47 | |
75 | |
48 | void psiconv_buffer_free(psiconv_buffer buf) |
76 | void psiconv_buffer_free(psiconv_buffer buf) |
49 | { |
77 | { |
|
|
78 | psiconv_list_free(buf->reloc_ref); |
|
|
79 | psiconv_list_free(buf->reloc_target); |
50 | psiconv_list_free(buf->data); |
80 | psiconv_list_free(buf->data); |
51 | free(buf); |
81 | free(buf); |
52 | } |
|
|
53 | |
|
|
54 | psiconv_u32 psiconv_buffer_base_offset(const psiconv_buffer buf) |
|
|
55 | { |
|
|
56 | return buf->base_offset; |
|
|
57 | } |
82 | } |
58 | |
83 | |
59 | psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf) |
84 | psiconv_u32 psiconv_buffer_length(const psiconv_buffer buf) |
60 | { |
85 | { |
61 | return psiconv_list_length(buf->data); |
86 | return psiconv_list_length(buf->data); |
… | |
… | |
87 | return psiconv_list_fwrite_all(buf->data,f); |
112 | return psiconv_list_fwrite_all(buf->data,f); |
88 | } |
113 | } |
89 | |
114 | |
90 | int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra) |
115 | int psiconv_buffer_concat(psiconv_buffer buf, const psiconv_buffer extra) |
91 | { |
116 | { |
|
|
117 | int res; |
|
|
118 | psiconv_u32 i; |
|
|
119 | psiconv_relocation reloc; |
|
|
120 | |
|
|
121 | |
|
|
122 | for (i = 0; i < psiconv_list_length(extra->reloc_target); i++) { |
|
|
123 | if (!(reloc = psiconv_list_get(extra->reloc_target,i))) |
|
|
124 | return -PSICONV_E_OTHER; |
|
|
125 | reloc->offset += psiconv_list_length(buf->data); |
|
|
126 | if ((res=psiconv_list_add(buf->reloc_target,reloc))) |
|
|
127 | return res; |
|
|
128 | } |
|
|
129 | for (i = 0; i < psiconv_list_length(extra->reloc_ref); i++) { |
|
|
130 | if (!(reloc = psiconv_list_get(extra->reloc_ref,i))) |
|
|
131 | return -PSICONV_E_OTHER; |
|
|
132 | reloc->offset += psiconv_list_length(buf->data); |
|
|
133 | if ((res = psiconv_list_add(buf->reloc_ref,reloc))) |
|
|
134 | return res; |
|
|
135 | } |
92 | return psiconv_list_concat(buf->data,extra->data); |
136 | return psiconv_list_concat(buf->data,extra->data); |
93 | } |
137 | } |
|
|
138 | |
|
|
139 | int psiconv_buffer_resolve(psiconv_buffer buf) |
|
|
140 | { |
|
|
141 | int res; |
|
|
142 | psiconv_u32 i,j,temp; |
|
|
143 | psiconv_relocation target,ref; |
|
|
144 | |
|
|
145 | for (i = 0; i < psiconv_list_length(buf->reloc_ref);i++) { |
|
|
146 | if (!(ref = psiconv_list_get(buf->reloc_ref,i))) |
|
|
147 | return -PSICONV_E_OTHER; |
|
|
148 | for (j = 0; j < psiconv_list_length(buf->reloc_target);j++) { |
|
|
149 | if (!(target = psiconv_list_get(buf->reloc_target,j))) |
|
|
150 | return -PSICONV_E_OTHER; |
|
|
151 | if (ref->id == target->id) { |
|
|
152 | temp = target->offset & 0xff; |
|
|
153 | if ((res = psiconv_list_replace(buf->data,ref->offset,&temp))) |
|
|
154 | return -PSICONV_E_OTHER; |
|
|
155 | temp = (target->offset >> 8) & 0xff; |
|
|
156 | if ((res = psiconv_list_replace(buf->data,ref->offset + 1,&temp))) |
|
|
157 | return -PSICONV_E_OTHER; |
|
|
158 | temp = (target->offset >> 16) & 0xff; |
|
|
159 | if ((res = psiconv_list_replace(buf->data,ref->offset + 2,&temp))) |
|
|
160 | return -PSICONV_E_OTHER; |
|
|
161 | temp = (target->offset >> 24) & 0xff; |
|
|
162 | if ((res = psiconv_list_replace(buf->data,ref->offset + 3,&temp))) |
|
|
163 | return -PSICONV_E_OTHER; |
|
|
164 | break; |
|
|
165 | } |
|
|
166 | } |
|
|
167 | if (j == psiconv_list_length(buf->reloc_target)) |
|
|
168 | return -PSICONV_E_OTHER; |
|
|
169 | } |
|
|
170 | psiconv_list_empty(buf->reloc_target); |
|
|
171 | psiconv_list_empty(buf->reloc_ref); |
|
|
172 | return -PSICONV_E_OK; |
|
|
173 | } |
|
|
174 | |
|
|
175 | int psiconv_buffer_add_reference(psiconv_buffer buf,int id) |
|
|
176 | { |
|
|
177 | struct psiconv_relocation_s reloc; |
|
|
178 | int res,i; |
|
|
179 | psiconv_u8 data; |
|
|
180 | |
|
|
181 | reloc.offset = psiconv_list_length(buf->data); |
|
|
182 | reloc.id = id; |
|
|
183 | if ((res = psiconv_list_add(buf->reloc_ref,&reloc))) |
|
|
184 | return res; |
|
|
185 | data = 0x00; |
|
|
186 | for (i = 0; i < 4; i++) |
|
|
187 | if ((res = psiconv_list_add(buf->data,&data))) |
|
|
188 | return res; |
|
|
189 | return -PSICONV_E_OK; |
|
|
190 | } |
|
|
191 | |
|
|
192 | int psiconv_buffer_add_target(psiconv_buffer buf, int id) |
|
|
193 | { |
|
|
194 | struct psiconv_relocation_s reloc; |
|
|
195 | |
|
|
196 | reloc.offset = psiconv_list_length(buf->data); |
|
|
197 | reloc.id = id; |
|
|
198 | return psiconv_list_add(buf->reloc_target,&reloc); |
|
|
199 | } |