add a missing section header table index conversion
[tangerine.git] / compiler / arossupport / readstruct.c
blob5ffa47fbfa0b22cbb6cf5939c52d08ca4e2c2379
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Read a big endian structure from a streamhook
6 Lang: english
7 */
9 #include <string.h>
10 #include <exec/memory.h>
11 #include <proto/dos.h>
12 #include <proto/exec.h>
13 #include <aros/debug.h>
14 #include <utility/hooks.h>
16 struct ReadLevel
18 struct MinNode node;
19 const IPTR * sd;
20 UBYTE * s;
21 int pos;
24 /******************************************************************************
26 NAME */
27 #include <stdio.h>
28 #include <aros/bigendianio.h>
29 #include <proto/alib.h>
31 BOOL ReadStruct (
33 /* SYNOPSIS */
34 struct Hook * hook,
35 APTR * dataptr,
36 void * stream,
37 const IPTR * sd)
39 /* FUNCTION
40 Reads one big endian structure from a streamhook.
42 INPUTS
43 hook - Streamhook
44 dataptr - Put the data here
45 stream - Read from this stream
46 sd - Description of the structure to be read. The first element
47 is the size of the structure.
49 RESULT
50 The function returns TRUE on success. On success, the value
51 read is written into dataptr. On failure, FALSE is returned and the
52 contents of dataptr are not changed.
54 NOTES
55 This function reads big endian values from a streamhook even on
56 little endian machines.
58 EXAMPLE
59 See below.
61 BUGS
63 SEE ALSO
64 ReadByte(), ReadWord(), ReadLong(), ReadFloat(), ReadDouble(),
65 ReadString(), ReadStruct(), WriteByte(), WriteWord(), WriteLong(),
66 WriteFloat(), WriteDouble(), WriteString(), WriteStruct()
68 HISTORY
70 ******************************************************************************/
72 struct MinList _list;
73 struct ReadLevel * curr;
75 # define list ((struct List *)&_list)
77 NEWLIST(list);
79 if (!(curr = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
80 return FALSE;
82 AddTail (list, (struct Node *)curr);
84 curr->sd = sd;
85 curr->pos = 0;
86 curr->s = NULL;
88 # define DESC curr->sd[curr->pos]
89 # define IDESC curr->sd[curr->pos ++]
91 for (;;)
93 if (!curr->pos)
95 if (!(curr->s = AllocMem (IDESC, MEMF_CLEAR)) )
96 goto error;
99 if (DESC == SDT_END)
100 break;
102 switch (IDESC)
104 case SDT_UBYTE: /* Read one 8bit byte */
105 if (!ReadByte (hook, (UBYTE *)(curr->s + IDESC), stream))
106 goto error;
108 break;
110 case SDT_UWORD: /* Read one 16bit word */
111 if (!ReadWord (hook, (UWORD *)(curr->s + IDESC), stream))
112 goto error;
114 break;
116 case SDT_ULONG: /* Read one 32bit long */
117 if (!ReadLong (hook, (ULONG *)(curr->s + IDESC), stream))
118 goto error;
120 break;
122 case SDT_FLOAT: /* Read one 32bit IEEE */
123 if (!ReadFloat (hook, (FLOAT *)(curr->s + IDESC), stream))
124 goto error;
126 break;
128 case SDT_DOUBLE: /* Read one 64bit IEEE */
129 if (!ReadDouble (hook, (DOUBLE *)(curr->s + IDESC), stream))
130 goto error;
132 break;
134 case SDT_STRING: { /* Read a string */
135 UBYTE valid_ptr;
136 STRPTR * sptr;
138 sptr = (STRPTR *)(curr->s + IDESC);
140 if (!ReadByte (hook, &valid_ptr, stream))
141 goto error;
143 if (valid_ptr)
145 if (!ReadString (hook, sptr, stream))
146 goto error;
148 else
150 *sptr = NULL;
153 break; }
155 case SDT_STRUCT: { /* Read a structure */
156 struct ReadLevel * next;
157 IPTR * desc;
158 APTR aptr;
160 aptr = (APTR)(curr->s + IDESC);
161 desc = (IPTR *)IDESC;
163 curr->pos -= 3; /* Go back to type */
165 if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
166 goto error;
168 AddTail (list, (struct Node *)next);
169 next->sd = desc;
170 next->pos = 1;
171 next->s = aptr;
173 curr = next;
175 break; }
177 case SDT_PTR: { /* Follow a pointer */
178 struct ReadLevel * next;
180 UBYTE valid_ptr;
181 IPTR * desc;
182 APTR * aptr;
184 aptr = ((APTR *)(curr->s + IDESC));
185 desc = (IPTR *)IDESC;
187 if (!ReadByte (hook, &valid_ptr, stream))
188 goto error;
190 if (valid_ptr)
192 curr->pos -= 3;
194 if (!(next = AllocMem (sizeof (struct ReadLevel), MEMF_ANY)) )
195 goto error;
197 AddTail (list, (struct Node *)next);
198 next->sd = desc;
199 next->pos = 0;
201 curr = next;
203 else
205 *aptr = NULL;
208 break; }
210 case SDT_IGNORE: { /* Ignore x bytes */
211 struct BEIOM_Ignore ig = {BEIO_IGNORE, IDESC};
212 if (CallHookA (hook, stream, &ig) == EOF)
213 goto error;
215 break; }
217 case SDT_FILL_BYTE: { /* Fill x bytes */
218 IPTR offset;
219 UBYTE value;
220 IPTR count;
222 offset = IDESC;
223 value = IDESC;
224 count = IDESC;
226 memset (curr->s + offset, value, count);
228 break; }
230 case SDT_FILL_LONG: { /* Fill x longs */
231 ULONG * ulptr;
232 ULONG value;
233 IPTR count;
235 ulptr = (ULONG *)(curr->s + IDESC);
236 value = IDESC;
237 count = IDESC;
239 while (count --)
240 *ulptr ++ = value;
242 break; }
244 case SDT_IFILL_BYTE: { /* Fill x bytes */
245 IPTR offset;
246 UBYTE value;
247 IPTR count;
249 offset = IDESC;
250 value = IDESC;
251 count = IDESC;
253 struct BEIOM_Ignore ig = {BEIO_IGNORE, count};
255 if (CallHookA (hook, stream, &ig) == EOF)
256 goto error;
258 memset (curr->s + offset, value, count);
260 break; }
262 case SDT_IFILL_LONG: { /* Fill x longs */
263 ULONG * ulptr;
264 ULONG value;
265 IPTR count;
267 ulptr = (ULONG *)(curr->s + IDESC);
268 value = IDESC;
269 count = IDESC;
271 struct BEIOM_Ignore ig = {BEIO_IGNORE, count << 2};
273 if (CallHookA (hook, stream, &ig) == EOF)
274 goto error;
276 while (count --)
277 *ulptr ++ = value;
279 break; }
281 case SDT_SPECIAL: { /* Call user hook */
282 struct Hook * uhook;
283 struct SDData data;
285 data.sdd_Dest = ((APTR)(curr->s + IDESC));
286 data.sdd_Mode = SDV_SPECIALMODE_READ;
287 data.sdd_Stream = stream;
289 uhook = (struct Hook *)IDESC;
291 if (!CallHookA (uhook, hook, &data))
292 goto error;
294 break; }
296 default:
297 goto error;
299 } /* switch */
301 /* End of the description list ? */
302 if (DESC == SDT_END)
304 struct ReadLevel * last;
306 /* Remove the current level */
307 last = curr;
308 Remove ((struct Node *)last);
310 /* Get the last level */
311 if ((curr = (struct ReadLevel *)GetTail (list)))
313 switch (IDESC)
315 case SDT_STRUCT:
316 curr->pos += 2; /* Skip 2 parameters */
317 break;
319 case SDT_PTR: {
320 APTR * aptr;
322 aptr = ((APTR *)(curr->s + IDESC));
323 curr->pos ++; /* Skip description parameter */
326 Now put the result of the current level in the
327 struct of the previous level.
329 *aptr = last->s;
331 break; }
335 FreeMem (last, sizeof (struct ReadLevel));
337 else
339 curr = last;
342 } /* while */
344 *dataptr = curr->s;
346 FreeMem (curr, sizeof (struct ReadLevel));
348 return TRUE;
350 error:
351 curr = (struct ReadLevel *)GetHead (list);
353 if (curr && curr->s)
354 FreeStruct (curr->s, curr->sd);
356 while ((curr = (struct ReadLevel *)RemTail (list)))
357 FreeMem (curr, sizeof (struct ReadLevel));
359 return FALSE;
360 } /* ReadStruct */
362 #ifdef TEST
363 #include <stdio.h>
364 #include <dos/dos.h>
365 #include <aros/structdesc.h>
366 #include <proto/alib.h>
368 struct Level1
370 BYTE l1_Byte;
371 LONG l1_Long;
374 struct MainLevel
376 BYTE ml_Byte;
377 UBYTE ml_UByte;
378 WORD ml_Word;
379 UWORD ml_UWord;
380 LONG ml_Long;
381 ULONG ml_ULong;
382 FLOAT ml_Float;
383 DOUBLE ml_Double;
384 STRPTR ml_String;
385 struct Level1 ml_Level1;
387 BYTE * ml_BytePtr;
388 WORD * ml_WordPtr;
389 LONG * ml_LongPtr;
390 FLOAT * ml_FloatPtr;
391 DOUBLE * ml_DoublePtr;
392 STRPTR * ml_StringPtr;
393 struct Level1 * ml_Level1Ptr;
396 IPTR ByteDesc[] = { sizeof(UBYTE), SDM_UBYTE(0), SDM_END };
397 IPTR WordDesc[] = { sizeof(UWORD), SDM_UWORD(0), SDM_END };
398 IPTR LongDesc[] = { sizeof(ULONG), SDM_ULONG(0), SDM_END };
399 IPTR FloatDesc[] = { sizeof(FLOAT), SDM_FLOAT(0), SDM_END };
400 IPTR DoubleDesc[] = { sizeof(DOUBLE), SDM_DOUBLE(0), SDM_END };
401 IPTR StringDesc[] = { sizeof(STRPTR), SDM_STRING(0), SDM_END };
403 #define O(x) offsetof(struct Level1,x)
404 IPTR Level1Desc[] =
406 sizeof (struct Level1),
407 SDM_UBYTE(O(l1_Byte)),
408 SDM_ULONG(O(l1_Long)),
409 SDM_END
412 #undef O
413 #define O(x) offsetof(struct MainLevel,x)
414 IPTR MainDesc[] =
416 sizeof (struct MainLevel),
417 SDM_UBYTE(O(ml_Byte)),
418 SDM_UBYTE(O(ml_UByte)),
419 SDM_UWORD(O(ml_Word)),
420 SDM_UWORD(O(ml_UWord)),
421 SDM_ULONG(O(ml_Long)),
422 SDM_ULONG(O(ml_ULong)),
423 SDM_FLOAT(O(ml_Float)),
424 SDM_DOUBLE(O(ml_Double)),
425 SDM_STRING(O(ml_String)),
426 SDM_STRUCT(O(ml_Level1),Level1Desc),
428 SDM_PTR(O(ml_BytePtr),ByteDesc),
429 SDM_PTR(O(ml_WordPtr),WordDesc),
430 SDM_PTR(O(ml_LongPtr),LongDesc),
431 SDM_PTR(O(ml_FloatPtr),FloatDesc),
432 SDM_PTR(O(ml_DoublePtr),DoubleDesc),
433 SDM_PTR(O(ml_StringPtr),StringDesc),
434 SDM_PTR(O(ml_Level1Ptr),Level1Desc),
436 SDM_END
439 LONG dosstreamhook (struct Hook * hook, BPTR fh, ULONG * msg);
441 struct Hook dsh =
443 { NULL, NULL }, HookEntry, (void *)dosstreamhook, NULL
446 LONG dosstreamhook (struct Hook * hook, BPTR fh, ULONG * msg)
448 LONG rc;
450 switch (*msg)
452 case BEIO_READ:
453 rc = FGetC (fh);
454 break;
456 case BEIO_WRITE:
457 rc = FPutC (fh, ((struct BEIOM_Write *)msg)->Data);
458 break;
460 case BEIO_IGNORE:
461 Flush (fh);
463 rc = Seek (fh, ((struct BEIOM_Ignore *)msg)->Count, OFFSET_CURRENT);
464 break;
468 return rc;
469 } /* dosstreamhook */
471 int main (int argc, char ** argv)
473 struct MainLevel demo =
475 (BYTE)0x88, 0xFF,
476 (WORD)0x8844, 0xFF77,
477 (LONG)0x88442211, 0xFF773311,
478 1.5, 1.75,
479 "Hallo",
480 { (BYTE)0x88, (LONG)0x88442211 },
481 /* ... */
483 BYTE b = (BYTE)0x88;
484 WORD w = (WORD)0x8844;
485 LONG l = (LONG)0x88442211;
486 FLOAT f = 1.5;
487 DOUBLE d = 1.75;
488 STRPTR s = "Hallo";
489 struct Level1 l1 =
491 (BYTE)0x88, (LONG)0x88442211
493 BPTR fh;
494 struct MainLevel * readback;
496 demo.ml_BytePtr = &b;
497 demo.ml_WordPtr = &w;
498 demo.ml_LongPtr = &l;
499 demo.ml_FloatPtr = &f;
500 demo.ml_DoublePtr = &d;
501 demo.ml_StringPtr = &s;
502 demo.ml_Level1Ptr = &l1;
504 fh = Open ("writestruct.dat", MODE_NEWFILE);
506 if (!fh)
508 PrintFault (IoErr(), "Can't open file\n");
509 return 10;
513 This writes the following data stream:
515 0000 88 ml_Byte
516 0001 ff ml_Ubyte
517 0002 88 44 ml_Word
518 0004 ff 77 ml_UWord
519 0006 88 44 22 11 ml_Long
520 000a ff 77 33 11 ml_ULong
521 000e 3f c0 00 00 ml_Float
522 0012 3f fc 00 00 00 00 00 00 ml_Double
523 001a 01:48 61 6c 6c 6f 00 ml_String
524 0021 88 ml_Level1.l1_Byte
525 0022 88 44 22 11 ml_Level1.l1_Long
526 0026 01:88 ml_BytePtr
527 0028 01:88 44 ml_WordPtr
528 002b 01:88 44 22 11 ml_LongPtr
529 0030 01:3f c0 00 00 ml_FloatPtr
530 0035 01:3f fc 00 00 00 00 00 00 ml_DoublePtr
531 003e 01:01:48 61 6c 6c 6f 00 ml_StringPtr - Note two 01 !
532 0046 01:88 88 44 22 11 ml_Level1Ptr
535 if (!WriteStruct (&dsh, &demo, fh, MainDesc))
537 PrintFault (IoErr(), "Failed to write to file\n");
540 if (!Close (fh))
542 PrintFault (IoErr(), "Failed to close file\n");
545 /* Read the structure back */
546 fh = Open ("writestruct.dat", MODE_OLDFILE);
548 if (!fh)
550 PrintFault (IoErr(), "Can't open file for reading\n");
551 return 10;
554 if (!ReadStruct (&dsh, (APTR *)&readback, fh, MainDesc))
556 PrintFault (IoErr(), "Failed to read from file\n");
558 else
560 UBYTE * ptr;
561 int t;
563 ptr = (UBYTE *)readback;
564 t = 0;
566 kprintf ("readback = %p\n", readback);
568 kprintf ("%02X (88) %02X (FF)\n"
569 , (UBYTE)readback->ml_Byte
570 , readback->ml_UByte
572 kprintf ("%04X (8844) %04X (FF77)\n"
573 , (UWORD)readback->ml_Word
574 , readback->ml_UWord
576 kprintf ("%08lX (88442211) %08lX (FF773311)\n"
577 , readback->ml_Long
578 , readback->ml_ULong
580 kprintf ("%08lX (3FC00000) %08lX:%08lX (3FFC0000:00000000)\n"
581 , *(ULONG *)&readback->ml_Float
582 , ((ULONG *)&readback->ml_Double)[1]
583 , ((ULONG *)&readback->ml_Double)[0]
585 kprintf ("%s (Hallo)\n"
586 , readback->ml_String
588 kprintf ("{ %02X %08X } ({ 88 88442211 })\n"
589 , (UBYTE)readback->ml_Level1.l1_Byte
590 , readback->ml_Level1.l1_Long
592 kprintf ("%02X (88)\n"
593 , (UBYTE)*readback->ml_BytePtr
595 kprintf ("%04X (8844)\n"
596 , (UWORD)*readback->ml_WordPtr
598 kprintf ("%08lX (88442211)\n"
599 , *readback->ml_LongPtr
601 kprintf ("%08lX (3FC00000) %08lX:%08lX (3FFC0000:00000000)\n"
602 , *(ULONG *)readback->ml_FloatPtr
603 , ((ULONG *)readback->ml_DoublePtr)[1]
604 , ((ULONG *)readback->ml_DoublePtr)[0]
606 kprintf ("%s (Hallo)\n"
607 , *readback->ml_StringPtr
609 kprintf ("{ %02X %08X } ({ 88 88442211 })\n"
610 , (UBYTE)readback->ml_Level1Ptr->l1_Byte
611 , readback->ml_Level1Ptr->l1_Long
614 FreeStruct (readback, MainDesc);
617 if (!Close (fh))
619 PrintFault (IoErr(), "Failed to close file after reading\n");
622 return 0;
623 } /* main */
625 #endif /* TEST */