/[public]/psiconv/trunk/lib/psiconv/parse_simple.c
ViewVC logotype

Annotation of /psiconv/trunk/lib/psiconv/parse_simple.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 351 - (hide annotations)
Wed Oct 22 19:53:40 2014 UTC (5 years, 3 months ago) by frodo
File MIME type: text/plain
File size: 13194 byte(s)
(Frodo) Update copyright year in all source files

1 frodo 2 /*
2     parse_simple.c - Part of psiconv, a PSION 5 file formats converter
3 frodo 351 Copyright (c) 1999-2014 Frodo Looijaard <frodo@frodo.looijaard.name>
4 frodo 2
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18     */
19    
20     #include "config.h"
21 frodo 71 #include "compat.h"
22    
23 frodo 2 #include <stdlib.h>
24 frodo 101 #include <math.h>
25 frodo 2
26     #include "parse_routines.h"
27 frodo 71 #include "error.h"
28 frodo 184 #include "unicode.h"
29 frodo 2
30 frodo 142 #ifdef DMALLOC
31     #include <dmalloc.h>
32     #endif
33    
34 frodo 171 static psiconv_float_t pow2(int n);
35 frodo 182 static psiconv_string_t psiconv_read_string_aux(const psiconv_config config,
36     const psiconv_buffer buf,int lev,
37     psiconv_u32 off,int *length, int *status,
38     int kind);
39 frodo 171
40 frodo 118 /* Very inefficient, but good enough for now. By implementing it ourselves,
41     we do not have to link with -lm */
42     psiconv_float_t pow2(int n)
43     {
44     psiconv_float_t res=1.0;
45     int i;
46    
47     for (i = 0; i < (n<0?-n:n); i++)
48     res *= 2.0;
49    
50     return n<0?1/res:res;
51     }
52 frodo 168 psiconv_u8 psiconv_read_u8(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,
53 frodo 64 int *status)
54 frodo 2 {
55     psiconv_u8 *ptr;
56 frodo 79 ptr = psiconv_buffer_get(buf,off);
57 frodo 64 if (!ptr) {
58 frodo 184 psiconv_error(config,lev,off,"Trying byte read past the end of the file");
59 frodo 64 if (status)
60     *status = -PSICONV_E_PARSE;
61     return 0;
62     }
63     if (status)
64     *status = 0;
65 frodo 2 return *ptr;
66     }
67    
68 frodo 168 psiconv_u16 psiconv_read_u16(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,
69 frodo 64 int *status)
70 frodo 2 {
71     psiconv_u8 *ptr0,*ptr1;
72 frodo 79 ptr0 = psiconv_buffer_get(buf,off);
73     ptr1 = psiconv_buffer_get(buf,off+1);
74 frodo 64 if (!ptr0 || !ptr1) {
75 frodo 184 psiconv_error(config,lev,off,"Trying word read past the end of the file");
76 frodo 64 if (status)
77     *status = -PSICONV_E_PARSE;
78     return 0;
79     }
80     if (status)
81     *status = 0;
82 frodo 2 return *ptr0 + (*ptr1 << 8);
83     }
84    
85 frodo 168 psiconv_u32 psiconv_read_u32(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,
86 frodo 64 int *status)
87 frodo 2 {
88     psiconv_u8 *ptr0,*ptr1,*ptr2,*ptr3;
89 frodo 79 ptr0 = psiconv_buffer_get(buf,off);
90     ptr1 = psiconv_buffer_get(buf,off+1);
91     ptr2 = psiconv_buffer_get(buf,off+2);
92     ptr3 = psiconv_buffer_get(buf,off+3);
93 frodo 64 if (!ptr0 || !ptr1 || !ptr2 || !ptr3) {
94 frodo 184 psiconv_error(config,lev,off,"Trying long read past the end of the file");
95 frodo 64 if (status)
96     *status = -PSICONV_E_PARSE;
97     return 0;
98     }
99     if (status)
100     *status = 0;
101 frodo 2 return *ptr0 + (*ptr1 << 8) + (*ptr2 << 16) + (*ptr3 << 24);
102     }
103    
104 frodo 168 psiconv_s32 psiconv_read_sint(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,
105 frodo 129 int *length,int *status)
106     {
107     int localstatus;
108     psiconv_u32 temp;
109    
110 frodo 168 temp=psiconv_read_u32(config,buf,lev,off,&localstatus);
111 frodo 129 if (status)
112     *status = localstatus;
113     if (length)
114     *length = localstatus?0:4;
115    
116     return localstatus?0:(temp & 0x7fffffff)*(temp&0x80000000?-1:1);
117     }
118    
119 frodo 188 psiconv_u32 psiconv_read_S(const psiconv_config config,const psiconv_buffer buf, int lev, psiconv_u32 off,
120 frodo 64 int *length,int *status)
121 frodo 2 {
122     psiconv_u8 temp;
123 frodo 188 psiconv_u32 res;
124 frodo 64 int len,localstatus;
125 frodo 2
126 frodo 168 psiconv_progress(config,lev+1,off,"Going to read a S length indicator");
127     temp = psiconv_read_u8(config,buf,lev+2,off,&localstatus);
128 frodo 64 if (localstatus)
129     goto ERROR;
130 frodo 2 if ((temp & 0x03) == 0x02) {
131 frodo 168 res = psiconv_read_u8(config,buf,lev+2,off,&localstatus) >> 2;
132 frodo 64 if (localstatus)
133     goto ERROR;
134 frodo 2 len = 1;
135 frodo 168 psiconv_debug(config,lev+2,off,"Indicator (1 byte): %02x",res);
136 frodo 132 } else if ((temp & 0x07) == 0x05) {
137 frodo 168 res = psiconv_read_u16(config,buf,lev+2,off,&localstatus) >> 3;
138 frodo 64 if (localstatus)
139     goto ERROR;
140 frodo 2 len = 2;
141 frodo 168 psiconv_debug(config,lev+2,off,"Indicator (2 bytes): %04x",res);
142 frodo 2 } else {
143 frodo 184 psiconv_error(config,lev+2,off,"S indicator: unknown encoding!");
144 frodo 168 psiconv_debug(config,lev+2,off,"Raw data first byte: %02x",temp);
145 frodo 64 goto ERROR;
146 frodo 2 }
147    
148     if (length)
149     *length = len;
150 frodo 64 if (status)
151     *status = 0;
152 frodo 2
153 frodo 168 psiconv_progress(config,lev+1,off+len-1,
154 frodo 2 "End of S length indicator (total length: %08x)", len);
155    
156     return res;
157 frodo 64
158     ERROR:
159 frodo 184 psiconv_error(config,lev+1,off,"Reading of S indicator failed");
160 frodo 64 if (status)
161     *status = localstatus;
162     if (length)
163     *length = 0;
164     return 0;
165 frodo 2 }
166    
167 frodo 188 psiconv_u32 psiconv_read_X(const psiconv_config config,const psiconv_buffer buf, int lev, psiconv_u32 off,
168 frodo 64 int *length, int *status)
169 frodo 2 {
170     psiconv_u8 temp;
171 frodo 188 psiconv_u32 res;
172 frodo 64 int len,localstatus;
173 frodo 2
174 frodo 168 psiconv_progress(config,lev+1,off,"Going to read a X length indicator");
175     temp = psiconv_read_u8(config,buf,lev+2,off,&localstatus);
176 frodo 64 if (localstatus)
177     goto ERROR;
178 frodo 2 if ((temp & 0x01) == 0x00) {
179 frodo 168 res = psiconv_read_u8(config,buf,lev+2,off,&localstatus) >> 1;
180 frodo 64 if (localstatus)
181     goto ERROR;
182 frodo 2 len = 1;
183 frodo 168 psiconv_debug(config,lev+2,off,"Indicator (1 byte): %02x",res);
184 frodo 2 } else if ((temp & 0x03) == 0x01) {
185 frodo 168 res = psiconv_read_u16(config,buf,lev+2,off,&localstatus) >> 2;
186 frodo 64 if (localstatus)
187     goto ERROR;
188 frodo 2 len = 2;
189 frodo 168 psiconv_debug(config,lev+2,off,"Indicator (2 bytes): %04x",res);
190 frodo 2 } else if ((temp & 0x07) == 0x03) {
191 frodo 168 res = psiconv_read_u32(config,buf,lev+2,off,&localstatus) >> 3;
192 frodo 64 if (localstatus)
193     goto ERROR;
194 frodo 2 len = 4;
195 frodo 168 psiconv_debug(config,lev+2,off,"Indicator (4 bytes): %08x",res);
196 frodo 2 } else {
197 frodo 184 psiconv_error(config,lev+2,off,"X indicator: unknown encoding!");
198 frodo 168 psiconv_debug(config,lev+2,off,"Raw data first byte: %02x",temp);
199 frodo 64 goto ERROR;
200 frodo 2 }
201    
202     if (length)
203     *length = len;
204 frodo 64 if (status)
205     *status = 0;
206 frodo 2
207 frodo 168 psiconv_progress(config,lev+1,off+len-1,
208 frodo 2 "End of X length indicator (total length: %08x)", len);
209    
210     return res;
211 frodo 64
212     ERROR:
213 frodo 184 psiconv_error(config,lev+1,off,"Reading of X indicator failed");
214 frodo 64 if (status)
215     *status = localstatus;
216     if (length)
217     *length = 0;
218     return 0;
219 frodo 2 }
220    
221 frodo 168 psiconv_length_t psiconv_read_length(const psiconv_config config,const psiconv_buffer buf, int lev,
222 frodo 64 psiconv_u32 off, int *length, int *status)
223 frodo 2 {
224     psiconv_length_t res;
225 frodo 64 int localstatus;
226    
227 frodo 168 res = (2.54/1440.0) * ((psiconv_s32) psiconv_read_u32(config,buf,lev,off,
228 frodo 64 &localstatus));
229     if (localstatus) {
230 frodo 184 psiconv_error(config,lev+1,off,"Reading of length failed");
231 frodo 64 if (length)
232     *length = 0;
233     if (status)
234     *status = localstatus;
235     return 0;
236     }
237 frodo 168 psiconv_debug(config,lev+1,off,"Length: %f",res);
238 frodo 2 if (length)
239     *length = 4;
240 frodo 64 if (status)
241     *status = 0;
242 frodo 2 return res;
243     }
244    
245 frodo 168 psiconv_size_t psiconv_read_size(const psiconv_config config,const psiconv_buffer buf, int lev,
246 frodo 64 psiconv_u32 off, int *length, int *status)
247 frodo 2 {
248     psiconv_size_t res;
249 frodo 64 int localstatus;
250 frodo 168 res = ((psiconv_s32) psiconv_read_u32(config,buf,lev,off,&localstatus)) / 20.0;
251 frodo 64 if (localstatus) {
252 frodo 184 psiconv_error(config,lev+1,off,"Reading of size failed");
253 frodo 64 if (length)
254     *length = 0;
255     if (status)
256     *status = localstatus;
257     return 0;
258     }
259 frodo 168 psiconv_debug(config,lev+1,off,"Size: %f",res);
260 frodo 64 if (status)
261     *status = 0;
262 frodo 2 if (length)
263     *length = 4;
264     return res;
265     }
266    
267 frodo 168 int psiconv_parse_bool(const psiconv_config config,const psiconv_buffer buf, int lev, psiconv_u32 off,
268 frodo 2 int *length, psiconv_bool_t *result)
269     {
270     psiconv_u8 temp;
271 frodo 64 int localstatus;
272 frodo 168 temp = psiconv_read_u8(config,buf,lev,off,&localstatus);
273 frodo 64 if (localstatus) {
274 frodo 184 psiconv_error(config,lev+1,off,"Reading of bool failed");
275 frodo 64 if (length)
276     *length = 0;
277     return localstatus;
278     }
279 frodo 2 if (length)
280     *length = 1;
281     if (temp == 0) {
282     *result = psiconv_bool_false;
283     return 0;
284     } else if (temp == 1) {
285     *result = psiconv_bool_true;
286     return 0;
287     }
288 frodo 168 psiconv_warn(config,lev+1,off,"Unknown value for boolean");
289     psiconv_debug(config,lev+1,off,"Boolean value: %02x",temp);
290 frodo 2 *result = psiconv_bool_true;
291 frodo 64 return 0;
292 frodo 2 }
293    
294 frodo 182 psiconv_string_t psiconv_read_string(const psiconv_config config,
295     const psiconv_buffer buf,int lev,
296 frodo 64 psiconv_u32 off,int *length, int *status)
297 frodo 2 {
298 frodo 184 return psiconv_read_string_aux(config,buf,lev,off,length,status,-1);
299 frodo 182 }
300    
301     psiconv_string_t psiconv_read_short_string(const psiconv_config config,
302     const psiconv_buffer buf,int lev,
303     psiconv_u32 off,int *length, int *status)
304     {
305 frodo 184 return psiconv_read_string_aux(config,buf,lev,off,length,status,-2);
306 frodo 182 }
307    
308 frodo 184 psiconv_string_t psiconv_read_charlist(const psiconv_config config,
309     const psiconv_buffer buf, int lev,
310     psiconv_u32 off, int nrofchars,
311     int *status)
312     {
313     int length;
314     if (nrofchars <= 0) {
315     psiconv_error(config,lev,off,
316     "psiconv_read_charlist called with non-positive nrofchars");
317     if (status)
318     *status = -PSICONV_E_OTHER;
319     return NULL;
320     }
321     return psiconv_read_string_aux(config,buf,lev,off,&length,status,nrofchars);
322     }
323    
324    
325 frodo 182 psiconv_string_t psiconv_read_string_aux(const psiconv_config config,
326     const psiconv_buffer buf,int lev,
327     psiconv_u32 off,int *length, int *status,
328     int kind)
329     {
330 frodo 217 int bytecount,i,leng,len,localstatus;
331 frodo 2 psiconv_string_t result;
332     char *res_copy;
333 frodo 217 psiconv_list string;
334     psiconv_ucs2 nextchar;
335     psiconv_ucs2 *nextcharptr;
336 frodo 2
337 frodo 168 psiconv_progress(config,lev+1,off,"Going to read a string");
338 frodo 2
339 frodo 184 if (kind == -1)
340 frodo 217 bytecount = psiconv_read_S(config,buf,lev+2,off,&leng,&localstatus);
341 frodo 184 else if (kind == -2) {
342 frodo 217 bytecount = psiconv_read_u8(config,buf,lev+2,off,&localstatus);
343 frodo 182 leng = 1;
344 frodo 184 } else {
345 frodo 217 bytecount = kind;
346 frodo 184 leng = 0;
347     localstatus = 0;
348 frodo 182 }
349 frodo 64 if (localstatus)
350     goto ERROR1;
351 frodo 217 psiconv_debug(config,lev+2,off,"Length: %i",bytecount);
352 frodo 2 len = leng;
353    
354 frodo 217 if (!(string = psiconv_list_new(sizeof(*result))))
355 frodo 64 goto ERROR1;
356 frodo 217
357     /* Read the string into a temporary list */
358     i = 0;
359     while (i < bytecount) {
360     nextchar = psiconv_unicode_read_char(config,buf,lev,off+i+len,
361     &leng,&localstatus);
362 frodo 184 if (localstatus)
363     goto ERROR2;
364 frodo 217 if ((localstatus = psiconv_list_add(string,&nextchar)))
365     goto ERROR2;
366     i += leng;
367 frodo 184 }
368 frodo 217 if (i > bytecount) {
369     psiconv_error(config,lev,off+i+len,"Malformed string");
370     localstatus = PSICONV_E_PARSE;
371     goto ERROR2;
372     }
373     len += bytecount;
374 frodo 2
375 frodo 217 /* Copy the list to the actual string */
376     if (!(result = malloc(sizeof(*result) * (psiconv_list_length(string) + 1))))
377     goto ERROR2;
378     for (i = 0; i < psiconv_list_length(string); i++) {
379     if (!(nextcharptr = psiconv_list_get(string,i))) {
380 frodo 233 psiconv_error(config,lev,off+i+len,"Data structure corruption");
381 frodo 217 goto ERROR3;
382     }
383     result[i] = *nextcharptr;
384     }
385     result[i] = 0;
386    
387 frodo 184 res_copy = psiconv_make_printable(config,result);
388 frodo 64 if (!res_copy)
389 frodo 217 goto ERROR3;
390 frodo 168 psiconv_debug(config,lev+2,off,"Contents: `%s'",res_copy);
391 frodo 2 free(res_copy);
392    
393 frodo 217 psiconv_list_free(string);
394    
395 frodo 2 if (length)
396     *length = len;
397    
398 frodo 64 if (status)
399     *status = 0;
400    
401 frodo 168 psiconv_progress(config,lev+1,off+len-1,"End of string (total length: %08x)",len);
402 frodo 2
403     return result;
404 frodo 64
405 frodo 217 ERROR3:
406     free(result);
407 frodo 64 ERROR2:
408 frodo 217 psiconv_list_free(string);
409 frodo 64 ERROR1:
410 frodo 184 psiconv_error(config,lev+1,off,"Reading of string failed");
411 frodo 64 if (status)
412     *status = localstatus;
413     if (length)
414     *length = 0;
415     return NULL;
416 frodo 2 }
417 frodo 101
418 frodo 168 psiconv_float_t psiconv_read_float(const psiconv_config config,const psiconv_buffer buf, int lev,
419 frodo 101 psiconv_u32 off, int *length, int *status)
420     {
421     psiconv_float_t result,bitvalue;
422     int res,bit;
423     psiconv_u32 temp=0;
424    
425 frodo 168 psiconv_progress(config,lev+1,off,"Going to read a float");
426 frodo 101
427     bitvalue = 0.5;
428     result = 1.0;
429     for (bit = 0x33; bit > 0; bit--) {
430     if ((bit == 0x33) || ((bit & 0x07) == 0x07))
431 frodo 168 temp = psiconv_read_u8(config,buf,lev+2,off+ (bit >> 3),&res);
432 frodo 101 if (res)
433     goto ERROR;
434     if (temp & (0x01 << (bit & 0x07)))
435     result += bitvalue;
436     bitvalue /= 2.0;
437     }
438 frodo 168 temp = psiconv_read_u16(config,buf,lev+2,off+6,&res);
439 frodo 101 if (res)
440     goto ERROR;
441     if (temp & 0x8000)
442     result = -result;
443     temp = (temp & 0x7ff0) >> 4;
444 frodo 118 result *= pow2(((int) temp)-0x3ff);
445 frodo 168 psiconv_debug(config,lev+1,off,"Float value: %f",result);
446 frodo 101 if (length)
447     *length = 8;
448     if (*status)
449     *status = res;
450     return result;
451     ERROR:
452 frodo 184 psiconv_error(config,lev+1,off,"Reading of float failed");
453 frodo 101 if (length)
454     *length = 0;
455     if (*status)
456     *status = res;
457     return 0.0;
458     }
459 frodo 118

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26